diff --git a/.codecov.yml b/.codecov.yml new file mode 100644 index 000000000..a3ed7f477 --- /dev/null +++ b/.codecov.yml @@ -0,0 +1,14 @@ +# Codecov configuration to make it a bit less noisy +coverage: + status: + patch: false + project: + default: + threshold: 50% +comment: + layout: "header" + require_changes: false + branches: null + behavior: default + flags: null + paths: null \ No newline at end of file diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 000000000..9582c7873 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,42 @@ +# How to contribute + +We welcome contributions from external contributors, and this document +describes how to merge code changes into this openmmtools. + +## Getting Started + +* Make sure you have a [GitHub account](https://github.com/signup/free). +* [Fork](https://help.github.com/articles/fork-a-repo/) this repository on GitHub. +* On your local machine, + [clone](https://help.github.com/articles/cloning-a-repository/) your fork of + the repository. + +## Making Changes + +* Add some really awesome code to your local fork. It's usually a [good + idea](http://blog.jasonmeridth.com/posts/do-not-issue-pull-requests-from-your-master-branch/) + to make changes on a + [branch](https://help.github.com/articles/creating-and-deleting-branches-within-your-repository/) + with the branch name relating to the feature you are going to add. +* When you are ready for others to examine and comment on your new feature, + navigate to your fork of openmmtools on GitHub and open a [pull + request](https://help.github.com/articles/using-pull-requests/) (PR). Note that + after you launch a PR from one of your fork's branches, all + subsequent commits to that branch will be added to the open pull request + automatically. Each commit added to the PR will be validated for + mergability, compilation and test suite compliance; the results of these tests + will be visible on the PR page. +* If you're providing a new feature, you must add test cases and documentation. +* When the code is ready to go, make sure you run the test suite using pytest. +* When you're ready to be considered for merging, check the "Ready to go" + box on the PR page to let the openmmtools devs know that the changes are complete. + The code will not be merged until this box is checked, the continuous + integration returns checkmarks, + and multiple core developers give "Approved" reviews. + +# Additional Resources + +* [General GitHub documentation](https://help.github.com/) +* [PR best practices](http://codeinthehole.com/writing/pull-requests-and-other-good-practices-for-teams-using-github/) +* [A guide to contributing to software packages](http://www.contribution-guide.org) +* [Thinkful PR example](http://www.thinkful.com/learn/github-pull-request-tutorial/#Time-to-Submit-Your-First-PR) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index a7ef2650d..60c2e74c0 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,4 +1,11 @@ - - [ ] Implement feature / fix bug - - [ ] Add [tests](https://github.com/choderalab/openmmtools/tree/master/openmmtools/tests) - - [ ] Update [documentation](https://github.com/choderalab/openmmtools/tree/master/docs) as needed - - [ ] Update [changelog](https://github.com/choderalab/openmmtools/blob/master/docs/releasehistory.rst) \ No newline at end of file +## Description +Provide a brief description of the PR's purpose here. + +## Todos +- [ ] Implement feature / fix bug +- [ ] Add [tests](https://github.com/choderalab/openmmtools/tree/master/openmmtools/tests) +- [ ] Update [documentation](https://github.com/choderalab/openmmtools/tree/master/docs) as needed +- [ ] Update [changelog](https://github.com/choderalab/openmmtools/blob/master/docs/releasehistory.rst)Notable points that this PR has either accomplished or will accomplish. + +## Status +- [ ] Ready to go diff --git a/.gitignore b/.gitignore index 6f8cee03a..e08538a58 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,102 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ *.py[cod] +*$py.class -openmmtools/version.py +# C extensions +*.so -# Packages -*.egg-info -dist -build -__pycache__ +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg -# PyCharm -.idea +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +.pytest_cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# dotenv +.env + +# virtualenv +.venv +venv/ +ENV/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ diff --git a/.lgtm.yml b/.lgtm.yml new file mode 100644 index 000000000..933988bfd --- /dev/null +++ b/.lgtm.yml @@ -0,0 +1,12 @@ +# Configure LGTM for this package + +extraction: + python: # Configure Python + python_setup: # Configure the setup + version: 3 # Specify Version 3 +path_classifiers: + library: + - versioneer.py # Set Versioneer.py to an external "library" (3rd party code) + - devtools/* + generated: + - openmmtools/_version.py diff --git a/.travis.yml b/.travis.yml index 33a92f67d..f7c7bcb7d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,46 +1,74 @@ -language: c -sudo: false -addons: - apt: - sources: - - ubuntu-toolchain-r-test +language: python -install: - - bash -x devtools/travis-ci/install.sh - - export PYTHONUNBUFFERED=true - - export PATH=$HOME/miniconda/bin:$PATH +# Run jobs on container-based infrastructure, can be overridden per job -script: - # Create a test environment - - conda create --quiet --yes -n test python=$python - # Activate the test environment - - source activate test - # Add org channel - - conda config --add channels ${ORGNAME} - # Add omnia dev channels - - if [ $DEVOMNIA ]; then conda config --add channels omnia-dev; fi - # Add conda-forge channel back to top priority - - conda config --add channels conda-forge - # Build the recipe - - conda build devtools/conda-recipe - # Install the package - - conda install --yes --quiet --use-local ${PACKAGENAME}-dev - # Install testing dependencies. Without specifying the numpy version, numpy - # is downgraded to 1.9 and we get a "libgfortran not found" issue. - - conda install --yes --quiet nose nose-timer pymbar "numpy>=1.14" - # Test the package - - cd devtools && nosetests $PACKAGENAME --nocapture --verbosity=2 --with-timer --with-doctest -a '!slow' && cd .. +matrix: + include: + # Extra includes for OSX since python language is not available by default on OSX + - os: osx + language: generic + env: PYTHON_VER=3.6 OPENMM="latest" + - os: osx + language: generic + env: PYTHON_VER=3.7 OPENMM="latest" + + - os: linux + language: generic # No need to set Python version since its conda + env: PYTHON_VER=3.6 OPENMM="latest" + - os: linux + language: generic + env: PYTHON_VER=3.7 OPENMM="latest" + + - os: linux + language: generic + env: PYTHON_VER=3.7 OPENMM="nightly" + - os: linux + language: generic + env: PYTHON_VER=3.7 OPENMM="conda-forge" + + allow_failures: + # TODO: Reactivate macOS tests if they stop segfaulting after switching from nose to pytest (see also #402 and #430). + - os: osx + # Allow conda-forge failure + - os: linux + language: generic + env: PYTHON_VER=3.7 OPENMM="conda-forge" env: - matrix: - - python=3.6 CONDA_PY=36 - - python=3.7 CONDA_PY=37 - - python=3.7 CONDA_PY=37 DEVOMNIA=true # allowed to fail global: - - ORGNAME="omnia" # the name of the organization - - PACKAGENAME="openmmtools" # the name of your package - OPENMM_CPU_THREADS="1" # only use one CPU thread for determinism -matrix: - allow_failures: - - env: python=3.7 CONDA_PY=37 DEVOMNIA=true +before_install: + # Additional info about the build + - uname -a + - df -h + - ulimit -a + + # Install the Python environment + - source devtools/travis-ci/before_install.sh + - python -V + +install: + + # Create test environment for package + - python devtools/scripts/create_conda_env.py -n=test -p=$PYTHON_VER devtools/conda-envs/test_env.yaml + # Activate the test environment + - conda activate test + # Build and install package + - python setup.py develop --no-deps + # Install desired OpenMM version + - if [ "$OPENMM" == "latest" ]; then echo "Using latest release OpenMM."; conda install --yes -c omnia openmm; fi + - if [ "$OPENMM" == "beta" ]; then echo "Using OpenMM beta"; conda install --yes -c omnia/label/beta openmm; fi + - if [ "$OPENMM" == "nightly" ]; then echo "Using OpenMM nightly dev build."; conda install --yes -c omnia-dev openmm; fi + - if [ "$OPENMM" == "conda-forge" ]; then echo "Using OpenMM conda-forge testing build."; conda install --yes -c conda-forge/label/testing openmm; conda remove --force ocl-icd ocl-icd-system; fi + + +script: + #- pytest -v --cov=openmmtools openmmtools/tests/ + - nosetests openmmtools/tests --nocapture --verbosity=2 --with-timer --with-doctest -a '!slow' + +notifications: + email: false + +after_success: + - codecov diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..1f73685a1 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,77 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, +body size, disability, ethnicity, gender identity and expression, level of +experience, nationality, personal appearance, race, religion, or sexual +identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +Moreover, project maintainers will strive to offer feedback and advice to +ensure quality and consistency of contributions to the code. Contributions +from outside the group of project maintainers are strongly welcomed but the +final decision as to whether commits are merged into the codebase rests with +the team of project maintainers. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an +appointed representative at an online or offline event. Representation of a +project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at 'john.chodera@choderalab.org'. The project team will +review and investigate all complaints, and will respond in a way that it deems +appropriate to the circumstances. The project team is obligated to maintain +confidentiality with regard to the reporter of an incident. Further details of +specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 1.4, available at +[http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/LICENSE b/LICENSE index eba7475aa..05498a993 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2015-2017 Chodera lab // Memorial Sloan Kettering Cancer Center +Copyright (c) 2015-2019 Chodera lab // Memorial Sloan Kettering Cancer Center Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 000000000..9b7f8e8a3 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,6 @@ +include LICENSE +include MANIFEST.in +include versioneer.py + +graft openmmtools +global-exclude *.py[cod] __pycache__ *.so \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index 05898e072..3be7a1e38 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,33 +1,46 @@ environment: - global: - # SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the - # /E:ON and /V:ON options are not enabled in the batch script intepreter - # See: http://stackoverflow.com/a/13751649/163740 - CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\devtools\\appveyor\\run_with_env.cmd" matrix: - - PYTHON: "C:\\Python35_64" - PYTHON_VERSION: "3.5" + - PYTHON: "C:\\Miniconda36-x64" + PYTHON_VERSION: "3.6" PYTHON_ARCH: "64" - CONDA_PY: "35" - CONDA_NPY: "112" - - PYTHON: "C:\\Python36_64" - PYTHON_VERSION: "3.6" + - PYTHON: "C:\\Miniconda37-x64" + PYTHON_VERSION: "3.7" PYTHON_ARCH: "64" - CONDA_PY: "36" - CONDA_NPY: "112" + install: - # this installs the appropriate Miniconda (Py2/Py3, 32/64 bit), - # as well as pip, conda-build, and the binstar CLI - - ps: . ".\\devtools\\appveyor\\install.ps1" + # Make sure pip is around + - python -m ensurepip - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" - - conda config --add channels omnia + + # Add conda-forge channel - conda config --add channels conda-forge - - conda config --add channels omnia/label/rc + + # Add omnia channel + - conda config --add channels omnia + + # Always run commands without asking + - conda config --set always_yes yes + + # Try to update conda first to avoid odd dependency clashes + - conda update --all + + # Create test environment for package + - python devtools\\scripts\\create_conda_env.py -n=test -p=%PYTHON_VERSION% devtools\\conda-envs\\test_env.yaml + + # Activate the test environment + - activate test + + # Build and install package + - python setup.py develop --no-deps + build: false test_script: - - "%CMD_IN_ENV% conda build --quiet devtools\\conda-recipe" + - pytest -v --cov=openmmtools openmmtools\\tests + +on_success: + - codecov diff --git a/devtools/README.md b/devtools/README.md index 998d59756..009e161ae 100644 --- a/devtools/README.md +++ b/devtools/README.md @@ -1,18 +1,60 @@ -Developer Notes / Tools -======================= +# Development, testing, and deployment tools -Assorted notes for developers. +This directory contains a collection of tools for running Continuous Integration (CI) tests, +conda installation, and other development tools not directly related to the coding process. -How to do a release -------------------- -- Update the whatsnew.rst document. Use the github view that shows all the commits to master since the last release to write it. -- Update the version number in `setup.py`, change `ISRELEASED` to `True` -- Commit to master, and [tag](https://github.com/choderalab/openmmtools/releases) the release on github -- To push the source to PyPI, use `python setup.py sdist --formats=gztar,zip upload` -- Conda binaries need to built separately on each platform (`conda build openmmtools; binstar upload `) -- Make an annoucement on github / email -- After tagging the release, make a NEW commit that changes `ISRELEASED` back to `False` in `setup.py` +## Manifest -It's important that the version which is tagged on github for the release be -the one with the ISRELEASED flag in setup.py set to true. +### Continuous Integration + +You should test your code, but do not feel compelled to use these specific programs. You also may not need Unix and +Windows testing if you only plan to deploy on specific platforms. These are just to help you get started + +* `travis-ci`: Linux and OSX based testing through [Travis-CI](https://about.travis-ci.com/) + * `before_install.sh`: Pip/Miniconda pre-package installation script for Travis +* `appveyor`: Windows based testing through [AppVeyor](https://www.appveyor.com/) (there are no files directly related to this) + +### Conda Environment: + +This directory contains the files to setup the Conda environment for testing purposes + +* `conda-envs`: directory containing the YAML file(s) which fully describe Conda Environments, their dependencies, and those dependency provenance's + * `test_env.yaml`: Simple test environment file with base dependencies. Channels are not specified here and therefore respect global Conda configuration + +### Additional Scripts: + +This directory contains OS agnostic helper scripts which don't fall in any of the previous categories +* `scripts` + * `create_conda_env.py`: Helper program for spinning up new conda environments based on a starter file with Python Version and Env. Name command-line options + + +## How to contribute changes +- Clone the repository if you have write access to the main repo, fork the repository if you are a collaborator. +- Make a new branch with `git checkout -b {your branch name}` +- Make changes and test your code +- Ensure that the test environment dependencies (`conda-envs`) line up with the build and deploy dependencies (`conda-recipe/meta.yaml`) +- Push the branch to the repo (either the main or your fork) with `git push -u origin {your branch name}` + * Note that `origin` is the default name assigned to the remote, yours may be different +- Make a PR on GitHub with your changes +- We'll review the changes and get your code into the repo after lively discussion! + + +## Checklist for updates +- [ ] Make sure there is an/are issue(s) opened for your specific update +- [ ] Create the PR, referencing the issue +- [ ] Debug the PR as needed until tests pass +- [ ] Tag the final, debugged version + * `git tag -a X.Y.Z [latest pushed commit] && git push --follow-tags` +- [ ] Get the PR merged in + +## Versioneer Auto-version +[Versioneer](https://github.com/warner/python-versioneer) will automatically infer what version +is installed by looking at the `git` tags and how many commits ahead this version is. The format follows +[PEP 440](https://www.python.org/dev/peps/pep-0440/) and has the regular expression of: +```regexp +\d+.\d+.\d+(?\+\d+-[a-z0-9]+) +``` +If the version of this commit is the same as a `git` tag, the installed version is the same as the tag, +e.g. `openmmtools-0.1.2`, otherwise it will be appended with `+X` where `X` is the number of commits +ahead from the last tag, and then `-YYYYYY` where the `Y`'s are replaced with the `git` commit hash. diff --git a/devtools/appveyor/install.ps1 b/devtools/appveyor/install.ps1 deleted file mode 100644 index 5e2f719bc..000000000 --- a/devtools/appveyor/install.ps1 +++ /dev/null @@ -1,91 +0,0 @@ -# Sample script to install Miniconda under Windows -# Authors: Olivier Grisel, Jonathan Helmus and Kyle Kastner, Robert McGibbon -# License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/ - -$MINICONDA_URL = "http://repo.continuum.io/miniconda/" - - -function DownloadMiniconda ($python_version, $platform_suffix) { - $webclient = New-Object System.Net.WebClient - $filename = "Miniconda3-4.5.4-Windows-" + $platform_suffix + ".exe" - $url = $MINICONDA_URL + $filename - - $basedir = $pwd.Path + "\" - $filepath = $basedir + $filename - if (Test-Path $filename) { - Write-Host "Reusing" $filepath - return $filepath - } - - # Download and retry up to 3 times in case of network transient errors. - Write-Host "Downloading" $filename "from" $url - $retry_attempts = 2 - for($i=0; $i -lt $retry_attempts; $i++){ - try { - $webclient.DownloadFile($url, $filepath) - break - } - Catch [Exception]{ - Start-Sleep 1 - } - } - if (Test-Path $filepath) { - Write-Host "File saved at" $filepath - } else { - # Retry once to get the error message if any at the last try - $webclient.DownloadFile($url, $filepath) - } - return $filepath -} - - -function InstallMiniconda ($python_version, $architecture, $python_home) { - Write-Host "Installing Python" $python_version "for" $architecture "bit architecture to" $python_home - if (Test-Path $python_home) { - Write-Host $python_home "already exists, skipping." - return $false - } - if ($architecture -match "32") { - $platform_suffix = "x86" - } else { - $platform_suffix = "x86_64" - } - - $filepath = DownloadMiniconda $python_version $platform_suffix - Write-Host "Installing" $filepath "to" $python_home - $install_log = $python_home + ".log" - $args = "/S /D=$python_home" - Write-Host $filepath $args - Start-Process -FilePath $filepath -ArgumentList $args -Wait -Passthru - if (Test-Path $python_home) { - Write-Host "Python $python_version ($architecture) installation complete" - } else { - Write-Host "Failed to install Python in $python_home" - Get-Content -Path $install_log - Exit 1 - } -} - - -function InstallCondaPackages ($python_home, $spec) { - $conda_path = $python_home + "\Scripts\conda.exe" - $args = "install --yes " + $spec - Write-Host ("conda " + $args) - Start-Process -FilePath "$conda_path" -ArgumentList $args -Wait -Passthru -} - -function UpdateConda ($python_home) { - $conda_path = $python_home + "\Scripts\conda.exe" - Write-Host "Updating conda..." - $args = "update --yes conda" - Write-Host $conda_path $args - Start-Process -FilePath "$conda_path" -ArgumentList $args -Wait -Passthru -} - -function main () { - InstallMiniconda $env:PYTHON_VERSION $env:PYTHON_ARCH $env:PYTHON - UpdateConda $env:PYTHON - InstallCondaPackages $env:PYTHON "conda-build pip jinja2 binstar" -} - -main diff --git a/devtools/appveyor/run_with_env.cmd b/devtools/appveyor/run_with_env.cmd deleted file mode 100644 index 3a472bc83..000000000 --- a/devtools/appveyor/run_with_env.cmd +++ /dev/null @@ -1,47 +0,0 @@ -:: To build extensions for 64 bit Python 3, we need to configure environment -:: variables to use the MSVC 2010 C++ compilers from GRMSDKX_EN_DVD.iso of: -:: MS Windows SDK for Windows 7 and .NET Framework 4 (SDK v7.1) -:: -:: To build extensions for 64 bit Python 2, we need to configure environment -:: variables to use the MSVC 2008 C++ compilers from GRMSDKX_EN_DVD.iso of: -:: MS Windows SDK for Windows 7 and .NET Framework 3.5 (SDK v7.0) -:: -:: 32 bit builds do not require specific environment configurations. -:: -:: Note: this script needs to be run with the /E:ON and /V:ON flags for the -:: cmd interpreter, at least for (SDK v7.0) -:: -:: More details at: -:: https://github.com/cython/cython/wiki/64BitCythonExtensionsOnWindows -:: http://stackoverflow.com/a/13751649/163740 -:: -:: Author: Olivier Grisel -:: License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/ -@ECHO OFF - -SET COMMAND_TO_RUN=%* -SET WIN_SDK_ROOT=C:\Program Files\Microsoft SDKs\Windows - -SET MAJOR_PYTHON_VERSION="%PYTHON_VERSION:~0,1%" -IF %MAJOR_PYTHON_VERSION% == "2" ( - SET WINDOWS_SDK_VERSION="v7.0" -) ELSE IF %MAJOR_PYTHON_VERSION% == "3" ( - SET WINDOWS_SDK_VERSION="v7.1" -) ELSE ( - ECHO Unsupported Python version: "%MAJOR_PYTHON_VERSION%" - EXIT 1 -) - -IF "%PYTHON_ARCH%"=="64" ( - ECHO Configuring Windows SDK %WINDOWS_SDK_VERSION% for Python %MAJOR_PYTHON_VERSION% on a 64 bit architecture - SET DISTUTILS_USE_SDK=1 - SET MSSdk=1 - "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Setup\WindowsSdkVer.exe" -q -version:%WINDOWS_SDK_VERSION% - "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Bin\SetEnv.cmd" /x64 /release - ECHO Executing: %COMMAND_TO_RUN% - call %COMMAND_TO_RUN% || EXIT 1 -) ELSE ( - ECHO Using default MSVC build environment for 32 bit architecture - ECHO Executing: %COMMAND_TO_RUN% - call %COMMAND_TO_RUN% || EXIT 1 -) diff --git a/devtools/conda-envs/test_env.yaml b/devtools/conda-envs/test_env.yaml new file mode 100644 index 000000000..84d3b6427 --- /dev/null +++ b/devtools/conda-envs/test_env.yaml @@ -0,0 +1,38 @@ +name: test +channels: + - conda-forge + - omnia + - defaults +dependencies: + # Base depends + - python + - pip + + - setuptools + - openmm >=7.3.1 + - cython + - python + - numpy + - scipy + - six + - openmm >=7.3.1 + - parmed + - mdtraj + - netcdf4 >=1.4.2 # after bugfix: "always return masked array by default, even if there are no masked values" + - libnetcdf >=4.6.2 # workaround for libssl issues + - pyyaml + - cython + - sphinxcontrib-bibtex + - mpiplus + - pymbar + + # Testing + - nose + - nose-timer + - pytest + - pytest-cov + - codecov + + # Pip-only installs + - pip: + #- codecov diff --git a/devtools/scripts/create_conda_env.py b/devtools/scripts/create_conda_env.py new file mode 100644 index 000000000..b51adc86d --- /dev/null +++ b/devtools/scripts/create_conda_env.py @@ -0,0 +1,95 @@ +import argparse +import os +import re +import glob +import shutil +import subprocess as sp +from tempfile import TemporaryDirectory +from contextlib import contextmanager +# YAML imports +try: + import yaml # PyYAML + loader = yaml.load +except ImportError: + try: + import ruamel_yaml as yaml # Ruamel YAML + except ImportError: + try: + # Load Ruamel YAML from the base conda environment + from importlib import util as import_util + CONDA_BIN = os.path.dirname(os.environ['CONDA_EXE']) + ruamel_yaml_path = glob.glob(os.path.join(CONDA_BIN, '..', + 'lib', 'python*.*', 'site-packages', + 'ruamel_yaml', '__init__.py'))[0] + # Based on importlib example, but only needs to load_module since its the whole package, not just + # a module + spec = import_util.spec_from_file_location('ruamel_yaml', ruamel_yaml_path) + yaml = spec.loader.load_module() + except (KeyError, ImportError, IndexError): + raise ImportError("No YAML parser could be found in this or the conda environment. " + "Could not find PyYAML or Ruamel YAML in the current environment, " + "AND could not find Ruamel YAML in the base conda environment through CONDA_EXE path. " + "Environment not created!") + loader = yaml.YAML(typ="safe").load # typ="safe" avoids odd typing on output + + +@contextmanager +def temp_cd(): + """Temporary CD Helper""" + cwd = os.getcwd() + with TemporaryDirectory() as td: + try: + os.chdir(td) + yield + finally: + os.chdir(cwd) + + +# Args +parser = argparse.ArgumentParser(description='Creates a conda environment from file for a given Python version.') +parser.add_argument('-n', '--name', type=str, + help='The name of the created Python environment') +parser.add_argument('-p', '--python', type=str, + help='The version of the created Python environment') +parser.add_argument('conda_file', + help='The file for the created Python environment') + +args = parser.parse_args() + +# Open the base file +with open(args.conda_file, "r") as handle: + yaml_script = loader(handle.read()) + +python_replacement_string = "python {}*".format(args.python) + +try: + for dep_index, dep_value in enumerate(yaml_script['dependencies']): + if re.match('python([ ><=*]+[0-9.*]*)?$', dep_value): # Match explicitly 'python' and its formats + yaml_script['dependencies'].pop(dep_index) + break # Making the assumption there is only one Python entry, also avoids need to enumerate in reverse +except (KeyError, TypeError): + # Case of no dependencies key, or dependencies: None + yaml_script['dependencies'] = [] +finally: + # Ensure the python version is added in. Even if the code does not need it, we assume the env does + yaml_script['dependencies'].insert(0, python_replacement_string) + +# Figure out conda path +if "CONDA_EXE" in os.environ: + conda_path = os.environ["CONDA_EXE"] +else: + conda_path = shutil.which("conda") +if conda_path is None: + raise RuntimeError("Could not find a conda binary in CONDA_EXE variable or in executable search path") + +print("CONDA ENV NAME {}".format(args.name)) +print("PYTHON VERSION {}".format(args.python)) +print("CONDA FILE NAME {}".format(args.conda_file)) +print("CONDA PATH {}".format(conda_path)) + +# Write to a temp directory which will always be cleaned up +with temp_cd(): + temp_file_name = "temp_script.yaml" + with open(temp_file_name, 'w') as f: + f.write(yaml.dump(yaml_script)) + sp.call("{} env create -n {} -f {}".format(conda_path, args.name, temp_file_name), shell=True) diff --git a/devtools/travis-ci/before_install.sh b/devtools/travis-ci/before_install.sh new file mode 100755 index 000000000..6d2fef577 --- /dev/null +++ b/devtools/travis-ci/before_install.sh @@ -0,0 +1,41 @@ +# Temporarily change directory to $HOME to install software +pushd . +cd $HOME +# Make sure some level of pip is installed +python -m ensurepip + +# Install Miniconda +if [ "$TRAVIS_OS_NAME" == "osx" ]; then + # Make OSX md5 mimic md5sum from linux, alias does not work + md5sum () { + command md5 -r "$@" + } + MINICONDA=Miniconda3-latest-MacOSX-x86_64.sh +else + MINICONDA=Miniconda3-latest-Linux-x86_64.sh +fi +MINICONDA_HOME=$HOME/miniconda +MINICONDA_MD5=$(wget -qO- https://repo.anaconda.com/miniconda/ | grep -A3 $MINICONDA | sed -n '4p' | sed -n 's/ *\(.*\)<\/td> */\1/p') +wget -q https://repo.anaconda.com/miniconda/$MINICONDA +if [[ $MINICONDA_MD5 != $(md5sum $MINICONDA | cut -d ' ' -f 1) ]]; then + echo "Miniconda MD5 mismatch" + exit 1 +fi +bash $MINICONDA -b -p $MINICONDA_HOME + +# Configure miniconda +export PIP_ARGS="-U" +# New to conda >=4.4 +echo ". $MINICONDA_HOME/etc/profile.d/conda.sh" >> ~/.bashrc # Source the profile.d file +echo "conda activate" >> ~/.bashrc # Activate conda +source ~/.bashrc # source file to get new commands +#export PATH=$MINICONDA_HOME/bin:$PATH # Old way, should not be needed anymore + +conda config --add channels conda-forge + +conda config --set always_yes yes +conda install conda conda-build jinja2 anaconda-client +conda update --quiet --all + +# Restore original directory +popd diff --git a/devtools/travis-ci/install.sh b/devtools/travis-ci/install.sh deleted file mode 100755 index 1bab8e1b1..000000000 --- a/devtools/travis-ci/install.sh +++ /dev/null @@ -1,23 +0,0 @@ -# Temporarily change directory to $HOME to install software -pushd . -cd $HOME - -# Install Miniconda -MINICONDA=Miniconda2-latest-Linux-x86_64.sh -MINICONDA_HOME=$HOME/miniconda -MINICONDA_MD5=$(curl -s https://repo.continuum.io/miniconda/ | grep -A3 $MINICONDA | sed -n '4p' | sed -n 's/ *\(.*\)<\/td> */\1/p') -wget -q https://repo.continuum.io/miniconda/$MINICONDA -if [[ $MINICONDA_MD5 != $(md5sum $MINICONDA | cut -d ' ' -f 1) ]]; then - echo "Miniconda MD5 mismatch" - exit 1 -fi -bash $MINICONDA -b -p $MINICONDA_HOME - -# Configure miniconda -export PIP_ARGS="-U" -export PATH=$MINICONDA_HOME/bin:$PATH -conda config --add channels conda-forge -conda install --yes conda\>=4.3 conda-build jinja2 anaconda-client pip - -# Restore original directory -popd diff --git a/docs/gettingstarted.rst b/docs/gettingstarted.rst index ab6112a73..affa7e9fc 100644 --- a/docs/gettingstarted.rst +++ b/docs/gettingstarted.rst @@ -761,7 +761,7 @@ part of a system. .. doctest:: - >>> # Prepare the T4 Lysozyme + p-xylene system for alchemical modification. + >>> # Prepare the host-guest system for alchemical modification. >>> guest_atoms = host_guest.mdtraj_topology.select('resname B2') >>> alchemical_region = alchemy.AlchemicalRegion(alchemical_atoms=guest_atoms) >>> factory = alchemy.AbsoluteAlchemicalFactory() @@ -786,8 +786,8 @@ Finally, let's mix Monte Carlo and dynamics for propagation. .. doctest:: >>> sequence_move = mcmc.SequenceMove(move_list=[ - ... mcmc.MCDisplacementMove(atom_subset=pxylene_atoms), - ... mcmc.MCRotationMove(atom_subset=pxylene_atoms), + ... mcmc.MCDisplacementMove(atom_subset=guest_atoms), + ... mcmc.MCRotationMove(atom_subset=guest_atoms), ... mcmc.LangevinSplittingDynamicsMove(timestep=2.0*unit.femtoseconds, n_steps=n_steps, ... reassign_velocities=True, n_restart_attempts=6) ... ]) diff --git a/docs/integrators.rst b/docs/integrators.rst index d3ed14234..4edcc20a6 100644 --- a/docs/integrators.rst +++ b/docs/integrators.rst @@ -46,6 +46,7 @@ These integrators are available for nonequilibrium switching simulations, and pr NonequilibriumLangevinIntegrator AlchemicalNonequilibriumLangevinIntegrator + PeriodicNonequilibriumIntegrator ExternalPerturbationLangevinIntegrator | diff --git a/docs/releasehistory.rst b/docs/releasehistory.rst index e6fc2958b..3981ad3a5 100644 --- a/docs/releasehistory.rst +++ b/docs/releasehistory.rst @@ -1,15 +1,71 @@ Release History *************** -0.19.0 -====== + +0.20.0 - Periodic alchemical integrators +======================================== + +Enhancements +------------ +- Add `PeriodicNonequilibriumIntegrator`, a simple extension of `AlchemicalNonequilibriumLangevinIntegrator` that supports periodic alchemical protocols +- ``SAMSSampler`` supports expanded ensemble simulations +- ``SAMSSampler`` accepts multiple criteria for switching the stage + +0.19.1 - Bugfix release +======================= + +Bugfixes +-------- +- Fixed a crash during the restraint unbiasing for systems with an unexpected order of atoms of receptor and ligands (`#462 `_). + + +0.19.0 - Multiple alchemical regions +==================================== New features ------------ +- Added support in ``AbsoluteAlchemicalFactory`` for handling multiple independent alchemical regions (`#438 `_). +- Added support for anisotropic and membrane barostats in `ThermodynamicState` (`#437 `_). +- Added support for platform properties in ContextCache (e.g. for mixed and double precision CUDA in multistate sampler) (`#437 `_). + +Bugfixes +-------- +- The multistate samplers now issue experimental API warnings via ``logger.warn()`` rather than ``warnings.warn()`` (`#446 `_). +- Fix return value in ``states.reduced_potential_at_states`` (`#444 `_). + +Known issues +------------ +- Using parallel MPI processes causes poor mixing of the odd thermodynamic states while the mixing of the even states is + normal. We're still investigating whether the issue is caused by a change in the MPI library or an internal bug. For + now, we recommend running calculations using only 1 GPU (see also `#449 `_ + and `yank#1130 `_). + +0.18.3 - Storage enhancements and bugfixes +========================================== + +Bugfixes +-------- +- Fixed a bug in ``multistateanalyzer.py`` where a function was imported from ``openmmtools.utils`` instead of ``openmmtools.multistate.utils`` (`#430 `_). +- Fixed a few imprecisions in the documentation (`#432 `_). + +Enhancements +------------ +- Writing on disk is much faster when the `checkpoint_interval` of multi-state samplers is large. This was due + to the dimension of the netcdf chunk size increasing with the checkpoint interval and surpassing the dimension + of the netcdf chunk cache. The chunk size of the iteration dimension is now always set to 1 (`#432 `_). + +0.18.2 - Bugfix release +======================= Bugfixes -------- +- A bug in the multistate samplers where``logsumexp`` was imported from ``scipy.misc`` (now in ``scipy.special``) was fixed (`#423 `_). +- Improve the robustness of opening the netcdf file on resuming of the multi-state samplers by setting the environment variable HDF5_USE_FILE_LOCKING to FALSE after 4 failed attempts (`#426 `_). +- Fixed a crash during exception handling (`#426 `_). +Other +----- +- Update build infrastructure to match `MolSSI cookiecutter `_ (`#424 `_, `#426 `_). 0.18.1 - Bugfix release ======================= @@ -36,7 +92,7 @@ New features - ``MultiStateSampler``: sample independently from multiple thermodynamic states - ``ReplicaExchangeSampler``: replica exchange among thermodynamic states - ``SAMSSampler``: self-adjusted mixture sampling (SAMS) sampling -- All samplers can use MPI via the ``mpiplus `_ package +- All samplers can use MPI via the `mpiplus `_ package 0.17.0 - Removed Py2 support, faster exact PME treatment ======================================================== diff --git a/docs/states.rst b/docs/states.rst index de73f6457..f9f2e3096 100644 --- a/docs/states.rst +++ b/docs/states.rst @@ -25,3 +25,15 @@ States IComposableState GlobalParameterFunction GlobalParameterState + +| + +Utility functions +----------------- + +.. currentmodule:: openmmtools.states +.. autosummary:: + :nosignatures: + :toctree: api/generated/ + + create_thermodynamic_state_protocol diff --git a/openmmtools/__init__.py b/openmmtools/__init__.py index 8511b4d2f..fb273c6da 100644 --- a/openmmtools/__init__.py +++ b/openmmtools/__init__.py @@ -5,8 +5,11 @@ """ -# Define global version. -from openmmtools import version -__version__ = version.version - from openmmtools import testsystems, integrators, alchemy, mcmc, states, cache, utils, constants, forces, forcefactories, storage, multistate + +# Handle versioneer +from ._version import get_versions +versions = get_versions() +__version__ = versions['version'] +__git_revision__ = versions['full-revisionid'] +del get_versions, versions diff --git a/openmmtools/_version.py b/openmmtools/_version.py new file mode 100644 index 000000000..d9171440d --- /dev/null +++ b/openmmtools/_version.py @@ -0,0 +1,520 @@ + +# This file helps to compute a version number in source trees obtained from +# git-archive tarball (such as those provided by githubs download-from-tag +# feature). Distribution tarballs (built by setup.py sdist) and build +# directories (produced by setup.py build) will contain a much shorter file +# that just contains the computed version number. + +# This file is released into the public domain. Generated by +# versioneer-0.18 (https://github.com/warner/python-versioneer) + +"""Git implementation of _version.py.""" + +import errno +import os +import re +import subprocess +import sys + + +def get_keywords(): + """Get the keywords needed to look up the version information.""" + # these strings will be replaced by git during git-archive. + # setup.py/versioneer.py will grep for the variable names, so they must + # each be defined on a line of their own. _version.py will just call + # get_keywords(). + git_refnames = "$Format:%d$" + git_full = "$Format:%H$" + git_date = "$Format:%ci$" + keywords = {"refnames": git_refnames, "full": git_full, "date": git_date} + return keywords + + +class VersioneerConfig: + """Container for Versioneer configuration parameters.""" + + +def get_config(): + """Create, populate and return the VersioneerConfig() object.""" + # these strings are filled in when 'setup.py versioneer' creates + # _version.py + cfg = VersioneerConfig() + cfg.VCS = "git" + cfg.style = "pep440" + cfg.tag_prefix = "" + cfg.parentdir_prefix = "None" + cfg.versionfile_source = "{{cookiecutter.repo_name}}/_version.py" + cfg.verbose = False + return cfg + + +class NotThisMethod(Exception): + """Exception raised if a method is not valid for the current scenario.""" + + +LONG_VERSION_PY = {} +HANDLERS = {} + + +def register_vcs_handler(vcs, method): # decorator + """Decorator to mark a method as the handler for a particular VCS.""" + def decorate(f): + """Store f in HANDLERS[vcs][method].""" + if vcs not in HANDLERS: + HANDLERS[vcs] = {} + HANDLERS[vcs][method] = f + return f + return decorate + + +def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, + env=None): + """Call the given command(s).""" + assert isinstance(commands, list) + p = None + for c in commands: + try: + dispcmd = str([c] + args) + # remember shell=False, so use git.cmd on windows, not just git + p = subprocess.Popen([c] + args, cwd=cwd, env=env, + stdout=subprocess.PIPE, + stderr=(subprocess.PIPE if hide_stderr + else None)) + break + except EnvironmentError: + e = sys.exc_info()[1] + if e.errno == errno.ENOENT: + continue + if verbose: + print("unable to run %s" % dispcmd) + print(e) + return None, None + else: + if verbose: + print("unable to find command, tried %s" % (commands,)) + return None, None + stdout = p.communicate()[0].strip() + if sys.version_info[0] >= 3: + stdout = stdout.decode() + if p.returncode != 0: + if verbose: + print("unable to run %s (error)" % dispcmd) + print("stdout was %s" % stdout) + return None, p.returncode + return stdout, p.returncode + + +def versions_from_parentdir(parentdir_prefix, root, verbose): + """Try to determine the version from the parent directory name. + + Source tarballs conventionally unpack into a directory that includes both + the project name and a version string. We will also support searching up + two directory levels for an appropriately named parent directory + """ + rootdirs = [] + + for i in range(3): + dirname = os.path.basename(root) + if dirname.startswith(parentdir_prefix): + return {"version": dirname[len(parentdir_prefix):], + "full-revisionid": None, + "dirty": False, "error": None, "date": None} + else: + rootdirs.append(root) + root = os.path.dirname(root) # up a level + + if verbose: + print("Tried directories %s but none started with prefix %s" % + (str(rootdirs), parentdir_prefix)) + raise NotThisMethod("rootdir doesn't start with parentdir_prefix") + + +@register_vcs_handler("git", "get_keywords") +def git_get_keywords(versionfile_abs): + """Extract version information from the given file.""" + # the code embedded in _version.py can just fetch the value of these + # keywords. When used from setup.py, we don't want to import _version.py, + # so we do it with a regexp instead. This function is not used from + # _version.py. + keywords = {} + try: + f = open(versionfile_abs, "r") + for line in f.readlines(): + if line.strip().startswith("git_refnames ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["refnames"] = mo.group(1) + if line.strip().startswith("git_full ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["full"] = mo.group(1) + if line.strip().startswith("git_date ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["date"] = mo.group(1) + f.close() + except EnvironmentError: + pass + return keywords + + +@register_vcs_handler("git", "keywords") +def git_versions_from_keywords(keywords, tag_prefix, verbose): + """Get version information from git keywords.""" + if not keywords: + raise NotThisMethod("no keywords at all, weird") + date = keywords.get("date") + if date is not None: + # git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant + # datestamp. However we prefer "%ci" (which expands to an "ISO-8601 + # -like" string, which we must then edit to make compliant), because + # it's been around since git-1.5.3, and it's too difficult to + # discover which version we're using, or to work around using an + # older one. + date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) + refnames = keywords["refnames"].strip() + if refnames.startswith("$Format"): + if verbose: + print("keywords are unexpanded, not using") + raise NotThisMethod("unexpanded keywords, not a git-archive tarball") + refs = set([r.strip() for r in refnames.strip("()").split(",")]) + # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of + # just "foo-1.0". If we see a "tag: " prefix, prefer those. + TAG = "tag: " + tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) + if not tags: + # Either we're using git < 1.8.3, or there really are no tags. We use + # a heuristic: assume all version tags have a digit. The old git %d + # expansion behaves like git log --decorate=short and strips out the + # refs/heads/ and refs/tags/ prefixes that would let us distinguish + # between branches and tags. By ignoring refnames without digits, we + # filter out many common branch names like "release" and + # "stabilization", as well as "HEAD" and "master". + tags = set([r for r in refs if re.search(r'\d', r)]) + if verbose: + print("discarding '%s', no digits" % ",".join(refs - tags)) + if verbose: + print("likely tags: %s" % ",".join(sorted(tags))) + for ref in sorted(tags): + # sorting will prefer e.g. "2.0" over "2.0rc1" + if ref.startswith(tag_prefix): + r = ref[len(tag_prefix):] + if verbose: + print("picking %s" % r) + return {"version": r, + "full-revisionid": keywords["full"].strip(), + "dirty": False, "error": None, + "date": date} + # no suitable tags, so version is "0+unknown", but full hex is still there + if verbose: + print("no suitable tags, using unknown + full revision id") + return {"version": "0+unknown", + "full-revisionid": keywords["full"].strip(), + "dirty": False, "error": "no suitable tags", "date": None} + + +@register_vcs_handler("git", "pieces_from_vcs") +def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): + """Get version from 'git describe' in the root of the source tree. + + This only gets called if the git-archive 'subst' keywords were *not* + expanded, and _version.py hasn't already been rewritten with a short + version string, meaning we're inside a checked out source tree. + """ + GITS = ["git"] + if sys.platform == "win32": + GITS = ["git.cmd", "git.exe"] + + out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, + hide_stderr=True) + if rc != 0: + if verbose: + print("Directory %s not under git control" % root) + raise NotThisMethod("'git rev-parse --git-dir' returned error") + + # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] + # if there isn't one, this yields HEX[-dirty] (no NUM) + describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", + "--always", "--long", + "--match", "%s*" % tag_prefix], + cwd=root) + # --long was added in git-1.5.5 + if describe_out is None: + raise NotThisMethod("'git describe' failed") + describe_out = describe_out.strip() + full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) + if full_out is None: + raise NotThisMethod("'git rev-parse' failed") + full_out = full_out.strip() + + pieces = {} + pieces["long"] = full_out + pieces["short"] = full_out[:7] # maybe improved later + pieces["error"] = None + + # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] + # TAG might have hyphens. + git_describe = describe_out + + # look for -dirty suffix + dirty = git_describe.endswith("-dirty") + pieces["dirty"] = dirty + if dirty: + git_describe = git_describe[:git_describe.rindex("-dirty")] + + # now we have TAG-NUM-gHEX or HEX + + if "-" in git_describe: + # TAG-NUM-gHEX + mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) + if not mo: + # unparseable. Maybe git-describe is misbehaving? + pieces["error"] = ("unable to parse git-describe output: '%s'" + % describe_out) + return pieces + + # tag + full_tag = mo.group(1) + if not full_tag.startswith(tag_prefix): + if verbose: + fmt = "tag '%s' doesn't start with prefix '%s'" + print(fmt % (full_tag, tag_prefix)) + pieces["error"] = ("tag '%s' doesn't start with prefix '%s'" + % (full_tag, tag_prefix)) + return pieces + pieces["closest-tag"] = full_tag[len(tag_prefix):] + + # distance: number of commits since tag + pieces["distance"] = int(mo.group(2)) + + # commit: short hex revision ID + pieces["short"] = mo.group(3) + + else: + # HEX: no tags + pieces["closest-tag"] = None + count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], + cwd=root) + pieces["distance"] = int(count_out) # total number of commits + + # commit date: see ISO-8601 comment in git_versions_from_keywords() + date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], + cwd=root)[0].strip() + pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) + + return pieces + + +def plus_or_dot(pieces): + """Return a + if we don't already have one, else return a .""" + if "+" in pieces.get("closest-tag", ""): + return "." + return "+" + + +def render_pep440(pieces): + """Build up version string, with post-release "local version identifier". + + Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you + get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty + + Exceptions: + 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += plus_or_dot(pieces) + rendered += "%d.g%s" % (pieces["distance"], pieces["short"]) + if pieces["dirty"]: + rendered += ".dirty" + else: + # exception #1 + rendered = "0+untagged.%d.g%s" % (pieces["distance"], + pieces["short"]) + if pieces["dirty"]: + rendered += ".dirty" + return rendered + + +def render_pep440_pre(pieces): + """TAG[.post.devDISTANCE] -- No -dirty. + + Exceptions: + 1: no tags. 0.post.devDISTANCE + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"]: + rendered += ".post.dev%d" % pieces["distance"] + else: + # exception #1 + rendered = "0.post.dev%d" % pieces["distance"] + return rendered + + +def render_pep440_post(pieces): + """TAG[.postDISTANCE[.dev0]+gHEX] . + + The ".dev0" means dirty. Note that .dev0 sorts backwards + (a dirty tree will appear "older" than the corresponding clean one), + but you shouldn't be releasing software with -dirty anyways. + + Exceptions: + 1: no tags. 0.postDISTANCE[.dev0] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += ".post%d" % pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + rendered += plus_or_dot(pieces) + rendered += "g%s" % pieces["short"] + else: + # exception #1 + rendered = "0.post%d" % pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + rendered += "+g%s" % pieces["short"] + return rendered + + +def render_pep440_old(pieces): + """TAG[.postDISTANCE[.dev0]] . + + The ".dev0" means dirty. + + Eexceptions: + 1: no tags. 0.postDISTANCE[.dev0] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += ".post%d" % pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + else: + # exception #1 + rendered = "0.post%d" % pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + return rendered + + +def render_git_describe(pieces): + """TAG[-DISTANCE-gHEX][-dirty]. + + Like 'git describe --tags --dirty --always'. + + Exceptions: + 1: no tags. HEX[-dirty] (note: no 'g' prefix) + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"]: + rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) + else: + # exception #1 + rendered = pieces["short"] + if pieces["dirty"]: + rendered += "-dirty" + return rendered + + +def render_git_describe_long(pieces): + """TAG-DISTANCE-gHEX[-dirty]. + + Like 'git describe --tags --dirty --always -long'. + The distance/hash is unconditional. + + Exceptions: + 1: no tags. HEX[-dirty] (note: no 'g' prefix) + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) + else: + # exception #1 + rendered = pieces["short"] + if pieces["dirty"]: + rendered += "-dirty" + return rendered + + +def render(pieces, style): + """Render the given version pieces into the requested style.""" + if pieces["error"]: + return {"version": "unknown", + "full-revisionid": pieces.get("long"), + "dirty": None, + "error": pieces["error"], + "date": None} + + if not style or style == "default": + style = "pep440" # the default + + if style == "pep440": + rendered = render_pep440(pieces) + elif style == "pep440-pre": + rendered = render_pep440_pre(pieces) + elif style == "pep440-post": + rendered = render_pep440_post(pieces) + elif style == "pep440-old": + rendered = render_pep440_old(pieces) + elif style == "git-describe": + rendered = render_git_describe(pieces) + elif style == "git-describe-long": + rendered = render_git_describe_long(pieces) + else: + raise ValueError("unknown style '%s'" % style) + + return {"version": rendered, "full-revisionid": pieces["long"], + "dirty": pieces["dirty"], "error": None, + "date": pieces.get("date")} + + +def get_versions(): + """Get version information or return default if unable to do so.""" + # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have + # __file__, we can work backwards from there to the root. Some + # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which + # case we can only use expanded keywords. + + cfg = get_config() + verbose = cfg.verbose + + try: + return git_versions_from_keywords(get_keywords(), cfg.tag_prefix, + verbose) + except NotThisMethod: + pass + + try: + root = os.path.realpath(__file__) + # versionfile_source is the relative path from the top of the source + # tree (where the .git directory might live) to this file. Invert + # this to find the root from __file__. + for i in cfg.versionfile_source.split('/'): + root = os.path.dirname(root) + except NameError: + return {"version": "0+unknown", "full-revisionid": None, + "dirty": None, + "error": "unable to find root of source tree", + "date": None} + + try: + pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose) + return render(pieces, cfg.style) + except NotThisMethod: + pass + + try: + if cfg.parentdir_prefix: + return versions_from_parentdir(cfg.parentdir_prefix, root, verbose) + except NotThisMethod: + pass + + return {"version": "0+unknown", "full-revisionid": None, + "dirty": None, + "error": "unable to compute version", "date": None} diff --git a/openmmtools/alchemy.py b/openmmtools/alchemy.py index ac1168bf1..b60618422 100644 --- a/openmmtools/alchemy.py +++ b/openmmtools/alchemy.py @@ -34,10 +34,11 @@ # ============================================================================= # GLOBAL IMPORTS # ============================================================================= - import copy import logging import collections +import itertools +import re import numpy as np from simtk import openmm, unit @@ -416,7 +417,8 @@ def apply_to_context(self, context): ('annihilate_electrostatics', True), ('annihilate_sterics', False), ('softcore_alpha', 0.5), ('softcore_a', 1), ('softcore_b', 1), ('softcore_c', 6), - ('softcore_beta', 0.0), ('softcore_d', 1), ('softcore_e', 1), ('softcore_f', 2) + ('softcore_beta', 0.0), ('softcore_d', 1), ('softcore_e', 1), ('softcore_f', 2), + ('name', None) ]) @@ -626,7 +628,8 @@ def __init__(self, consistent_exceptions=False, switch_width=1.0*unit.angstroms, self.disable_alchemical_dispersion_correction = disable_alchemical_dispersion_correction self.split_alchemical_forces = split_alchemical_forces - def create_alchemical_system(self, reference_system, alchemical_regions): + def create_alchemical_system(self, reference_system, alchemical_regions, + alchemical_regions_interactions=frozenset()): """Create an alchemically modified version of the reference system. To alter the alchemical state of the returned system use AlchemicalState. @@ -638,6 +641,10 @@ def create_alchemical_system(self, reference_system, alchemical_regions): alchemical system. This will not be modified. alchemical_regions : AlchemicalRegion The region of the reference system to alchemically soften. + alchemical_regions_interactions : Set[Tuple[int, int]], optional + Set of alchemical region index pairs for interacting regions. + By default, all alchemical regions interact only with the + non-alchemical environment. Returns ------- @@ -645,13 +652,40 @@ def create_alchemical_system(self, reference_system, alchemical_regions): Alchemically-modified version of reference_system. """ - # TODO implement multiple alchemical regions support. - if not isinstance(alchemical_regions, AlchemicalRegion): - raise NotImplemented('There is no support for multiple alchemical regions yet.') - alchemical_region = alchemical_regions + if alchemical_regions_interactions != frozenset(): + raise NotImplementedError('Interactions between alchemical regions is untested') + + logger.debug(f'Dictionary of interacting alchemical regions: {alchemical_regions_interactions}') + if isinstance(alchemical_regions, AlchemicalRegion): + alchemical_regions = [alchemical_regions] + logger.debug(f'Using {len(alchemical_regions)} alchemical regions') + + # Resolve alchemical regions. + alchemical_regions = [self._resolve_alchemical_region(reference_system, alchemical_region) + for alchemical_region in alchemical_regions] + + # Check for duplicate alchemical atoms/bonds/angles/torsions. + all_alchemical_elements = {element_type: set() for element_type in ['atoms', 'bonds', 'angles', 'torsions']} + + for alchemical_region in alchemical_regions: + for element_type, all_elements in all_alchemical_elements.items(): + # Ignore None alchemical elements. + region_elements = getattr(alchemical_region, 'alchemical_' + element_type) + if region_elements is None: + continue + + # Check if there are duplicates with previous regions. + duplicate_elements = all_elements & region_elements + if len(duplicate_elements) > 0: + raise ValueError('Two regions have duplicate {}.'.format(element_type)) - # Resolve alchemical region. - alchemical_region = self._resolve_alchemical_region(reference_system, alchemical_region) + # Update all alchemical elements. + all_alchemical_elements[element_type].update(region_elements) + + # Check for duplicate names + alchemical_region_names = {alchemical_region.name for alchemical_region in alchemical_regions} + if len(alchemical_region_names) != len(alchemical_regions): + raise ValueError('Two alchemical regions have the same name') # Record timing statistics. timer = utils.Timer() @@ -663,10 +697,11 @@ def create_alchemical_system(self, reference_system, alchemical_regions): alchemical_system = copy.deepcopy(reference_system) # Check that there are no virtual sites to alchemically modify. - for particle_index in range(reference_system.getNumParticles()): - if (reference_system.isVirtualSite(particle_index) and - particle_index in alchemical_region.alchemical_atoms): - raise ValueError('Alchemically modified virtual sites are not supported') + for alchemical_region in alchemical_regions: + for particle_index in alchemical_region.alchemical_atoms: + if reference_system.isVirtualSite(particle_index): + raise ValueError(f'Virtual atoms in region {alchemical_region.name}. ' + 'Alchemically modified virtual sites are not supported') # Modify forces as appropriate. We delete the forces that # have been processed modified at the end of the for loop. @@ -684,7 +719,8 @@ def create_alchemical_system(self, reference_system, alchemical_regions): # The reference system force will be deleted. forces_to_remove.append(force_index) # Collect all the Force objects modeling the reference force. - alchemical_forces = alchemical_force_creator_func(reference_force, alchemical_region) + alchemical_forces = alchemical_force_creator_func(reference_force, alchemical_regions, + alchemical_regions_interactions) for lambda_variable_name, lambda_forces in alchemical_forces.items(): try: alchemical_forces_by_lambda[lambda_variable_name].extend(lambda_forces) @@ -761,10 +797,10 @@ def get_energy_components(cls, alchemical_system, alchemical_state, positions, p energy_components = collections.OrderedDict() for force_label, force_index in force_labels.items(): energy_components[force_label] = context.getState(getEnergy=True, - groups=2**force_index).getPotentialEnergy() + groups=2**force_index).getPotentialEnergy() + # Clean up del context, integrator - return energy_components # ------------------------------------------------------------------------- @@ -1041,7 +1077,36 @@ def _add_alchemical_forces(self, alchemical_system, alchemical_forces_by_lambda) alchemical_system.addForce(force) @staticmethod - def _alchemically_modify_PeriodicTorsionForce(reference_force, alchemical_region): + def _are_straddling_noninteracting_regions(particles, alchemical_regions, alchemical_regions_interactions): + """Test if a set of particles are in two regions simultaneously and if these regions are interacting. + + Parameters + ---------- + particles: set + Set of particles to check if they are in two noninteracting alchemical regions. + alchemical_region : AlchemicalRegion + The alchemical region containing the indices of the torsions to test. + alchemical_regions_interactions : Set[Tuple[int, int]], optional + Set of alchemical region index pairs for interacting regions. + By default, all alchemical regions interact only with the + non-alchemical environment. + + """ + for i, alchemical_region_A in enumerate(alchemical_regions): + if alchemical_region_A.alchemical_atoms.intersection(particles): + j = 0 + while j < i: + alchemical_region_B = alchemical_regions[j] + if alchemical_region_B.alchemical_atoms.intersection(particles): + if {i, j} in alchemical_regions_interactions: + return False + else: + return True + j += 1 + return False + + @classmethod + def _alchemically_modify_PeriodicTorsionForce(cls, reference_force, alchemical_regions, alchemical_regions_interactions): """Create alchemically-modified version of PeriodicTorsionForce. Parameters @@ -1051,6 +1116,10 @@ def _alchemically_modify_PeriodicTorsionForce(reference_force, alchemical_region alchemical_region : AlchemicalRegion The alchemical region containing the indices of the torsions to alchemically modify. + alchemical_regions_interactions : Set[Tuple[int, int]], optional + Set of alchemical region index pairs for interacting regions. + By default, all alchemical regions interact only with the + non-alchemical environment. Returns ------- @@ -1062,37 +1131,66 @@ def _alchemically_modify_PeriodicTorsionForce(reference_force, alchemical_region in alchemical_region. """ + alchemical_forces = {} + all_alchemical_torsions = set() + # Don't create a force if there are no alchemical torsions. - if len(alchemical_region.alchemical_torsions) == 0: + for alchemical_region in alchemical_regions: + all_alchemical_torsions.update(alchemical_region.alchemical_torsions) + if len(all_alchemical_torsions) == 0: return {'': [copy.deepcopy(reference_force)]} # Create PeriodicTorsionForce to handle unmodified torsions. force = openmm.PeriodicTorsionForce() force.setForceGroup(reference_force.getForceGroup()) + for torsion_index in range(reference_force.getNumTorsions()): + particle1, particle2, particle3, particle4, periodicity, phase, k = reference_force.getTorsionParameters( + torsion_index) + particles = set((particle1, particle2, particle3, particle4)) + + # We don't connect through a torsion two particles that belong + # to two different and noninteracting alchemical regions. + are_straddling = cls._are_straddling_noninteracting_regions( + particles, alchemical_regions, alchemical_regions_interactions) + if (torsion_index not in all_alchemical_torsions) and (not are_straddling): + force.addTorsion(particle1, particle2, particle3, particle4, periodicity, phase, k) + + # Update the returned value with the non-alchemical force. + alchemical_forces[''] = [force] # Create CustomTorsionForce to handle alchemically modified torsions. - energy_function = "lambda_torsions*k*(1+cos(periodicity*theta-phase))" - custom_force = openmm.CustomTorsionForce(energy_function) - custom_force.addGlobalParameter('lambda_torsions', 1.0) - custom_force.addPerTorsionParameter('periodicity') - custom_force.addPerTorsionParameter('phase') - custom_force.addPerTorsionParameter('k') - # Process reference torsions. - for torsion_index in range(reference_force.getNumTorsions()): - # Retrieve parameters. - particle1, particle2, particle3, particle4, periodicity, phase, k = reference_force.getTorsionParameters(torsion_index) - # Create torsions. - if torsion_index in alchemical_region.alchemical_torsions: - # Alchemically modified torsion. + for alchemical_region in alchemical_regions: + # This region may not have torsions to modify. + if len(alchemical_region.alchemical_torsions) == 0: + continue + + # Check if the lambda variable needs a suffix to identify the region. + lambda_variable_name = 'lambda_torsions' + if alchemical_region.name is not None: + lambda_variable_name += '_' + alchemical_region.name + + # Create CustomTorsionForce to handle alchemically modified torsions. + energy_function = f"{lambda_variable_name}*k*(1+cos(periodicity*theta-phase))" + custom_force = openmm.CustomTorsionForce(energy_function) + custom_force.addGlobalParameter(lambda_variable_name, 1.0) + custom_force.addPerTorsionParameter('periodicity') + custom_force.addPerTorsionParameter('phase') + custom_force.addPerTorsionParameter('k') + + # Process reference torsions. + for torsion_index in sorted(alchemical_region.alchemical_torsions): + # Retrieve parameters. + particle1, particle2, particle3, particle4, periodicity, phase, k = reference_force.getTorsionParameters(torsion_index) + # Create torsions. custom_force.addTorsion(particle1, particle2, particle3, particle4, [periodicity, phase, k]) - else: - # Standard torsion. - force.addTorsion(particle1, particle2, particle3, particle4, periodicity, phase, k) - return {'': [force], 'lambda_torsions': [custom_force]} + # Update the returned value with the alchemical force. + alchemical_forces.update({lambda_variable_name: [custom_force]}) - @staticmethod - def _alchemically_modify_HarmonicAngleForce(reference_force, alchemical_region): + return alchemical_forces + + @classmethod + def _alchemically_modify_HarmonicAngleForce(cls, reference_force, alchemical_regions, alchemical_regions_interactions): """Create alchemically-modified version of HarmonicAngleForce Parameters @@ -1102,6 +1200,10 @@ def _alchemically_modify_HarmonicAngleForce(reference_force, alchemical_region): alchemical_region : AlchemicalRegion The alchemical region containing the indices of the angles to alchemically modify. + alchemical_regions_interactions : Set[Tuple[int, int]], optional + Set of alchemical region index pairs for interacting regions. + By default, all alchemical regions interact only with the + non-alchemical environment. Returns ------- @@ -1113,35 +1215,61 @@ def _alchemically_modify_HarmonicAngleForce(reference_force, alchemical_region): in alchemical_region. """ + alchemical_forces = {} + all_alchemical_angles = set() # Don't create a force if there are no alchemical angles. - if len(alchemical_region.alchemical_angles) == 0: + for alchemical_region in alchemical_regions: + all_alchemical_angles.update(alchemical_region.alchemical_angles) + if len(all_alchemical_angles) == 0: return {'': [copy.deepcopy(reference_force)]} # Create standard HarmonicAngleForce to handle unmodified angles. force = openmm.HarmonicAngleForce() force.setForceGroup(reference_force.getForceGroup()) - - # Create CustomAngleForce to handle alchemically modified angles. - energy_function = "lambda_angles*(K/2)*(theta-theta0)^2;" - custom_force = openmm.CustomAngleForce(energy_function) - custom_force.addGlobalParameter('lambda_angles', 1.0) - custom_force.addPerAngleParameter('theta0') - custom_force.addPerAngleParameter('K') - # Process reference angles. for angle_index in range(reference_force.getNumAngles()): - # Retrieve parameters. [particle1, particle2, particle3, theta0, K] = reference_force.getAngleParameters(angle_index) - if angle_index in alchemical_region.alchemical_angles: - # Alchemically modified angle. - custom_force.addAngle(particle1, particle2, particle3, [theta0, K]) - else: - # Standard angle. + particles = set((particle1, particle2, particle3)) + + # We don't connect through an angle two particles that belong + # to two different and noninteracting alchemical regions. + are_straddling = cls._are_straddling_noninteracting_regions( + particles, alchemical_regions, alchemical_regions_interactions) + if (angle_index not in all_alchemical_angles) and (not are_straddling): force.addAngle(particle1, particle2, particle3, theta0, K) - return {'': [force], 'lambda_angles': [custom_force]} + # Update the returned value with the non-alchemical force. + alchemical_forces[''] = [force] - @staticmethod - def _alchemically_modify_HarmonicBondForce(reference_force, alchemical_region): + # Create CustomAngleForce to handle alchemically modified angles. + for alchemical_region in alchemical_regions: + # This region may not have angles to modify. + if len(alchemical_region.alchemical_angles) == 0: + continue + + # Check if the lambda variable needs a suffix to identify the region. + lambda_variable_name = 'lambda_angles' + if alchemical_region.name is not None: + lambda_variable_name += '_' + alchemical_region.name + + # Create CustomAngleForce to handle alchemically modified angles. + energy_function = f"{lambda_variable_name}*(K/2)*(theta-theta0)^2;" + custom_force = openmm.CustomAngleForce(energy_function) + custom_force.addGlobalParameter(lambda_variable_name, 1.0) + custom_force.addPerAngleParameter('theta0') + custom_force.addPerAngleParameter('K') + + # Process reference angles. + for angle_index in sorted(alchemical_region.alchemical_angles): + [particle1, particle2, particle3, theta0, K] = reference_force.getAngleParameters(angle_index) + custom_force.addAngle(particle1, particle2, particle3, [theta0, K]) + + # Update the returned value with the alchemical force. + alchemical_forces.update({lambda_variable_name: [custom_force]}) + + return alchemical_forces + + @classmethod + def _alchemically_modify_HarmonicBondForce(cls, reference_force, alchemical_regions, alchemical_regions_interactions): """Create alchemically-modified version of HarmonicBondForce Parameters @@ -1151,6 +1279,10 @@ def _alchemically_modify_HarmonicBondForce(reference_force, alchemical_region): alchemical_region : AlchemicalRegion The alchemical region containing the indices of the bonds to alchemically modify. + alchemical_regions_interactions : Set[Tuple[int, int]], optional + Set of alchemical region index pairs for interacting regions. + By default, all alchemical regions interact only with the + non-alchemical environment. Returns ------- @@ -1162,49 +1294,128 @@ def _alchemically_modify_HarmonicBondForce(reference_force, alchemical_region): in alchemical_region. """ + alchemical_forces = {} + all_alchemical_bonds = set() + # Don't create a force if there are no alchemical bonds. - if len(alchemical_region.alchemical_bonds) == 0: + for alchemical_region in alchemical_regions: + all_alchemical_bonds.update(alchemical_region.alchemical_bonds) + if len(all_alchemical_bonds) == 0: return {'': [copy.deepcopy(reference_force)]} # Create standard HarmonicBondForce to handle unmodified bonds. force = openmm.HarmonicBondForce() force.setForceGroup(reference_force.getForceGroup()) - - # Create CustomBondForce to handle alchemically modified bonds. - energy_function = "lambda_bonds*(K/2)*(r-r0)^2;" - custom_force = openmm.CustomBondForce(energy_function) - custom_force.addGlobalParameter('lambda_bonds', 1.0) - custom_force.addPerBondParameter('r0') - custom_force.addPerBondParameter('K') - # Process reference bonds. for bond_index in range(reference_force.getNumBonds()): - # Retrieve parameters. [particle1, particle2, theta0, K] = reference_force.getBondParameters(bond_index) - if bond_index in alchemical_region.alchemical_bonds: - # Alchemically modified bond. + particles = set((particle1, particle2)) + + # We don't connect through a bond two particles that belong + # to two different and noninteracting alchemical regions. + are_straddling = cls._are_straddling_noninteracting_regions( + particles, alchemical_regions, alchemical_regions_interactions) + if (bond_index not in all_alchemical_bonds) and (not are_straddling): + force.addBond(particle1, particle2, theta0, K) + + # Update the returned value with the non-alchemical force. + alchemical_forces[''] = [force] + + for alchemical_region in alchemical_regions: + # This region may not have bonds to modify. + if len(alchemical_region.alchemical_bonds) == 0: + continue + + # Check if the lambda variable needs a suffix to identify the region. + lambda_variable_name = 'lambda_bonds' + if alchemical_region.name is not None: + lambda_variable_name += '_' + alchemical_region.name + + # Define force here so that it is over writen saving only one copy. + # Create CustomBondForce to handle alchemically modified bonds. + energy_function = f"{lambda_variable_name}*(K/2)*(r-r0)^2;" + custom_force = openmm.CustomBondForce(energy_function) + custom_force.addGlobalParameter(lambda_variable_name, 1.0) + custom_force.addPerBondParameter('r0') + custom_force.addPerBondParameter('K') + # Process reference bonds. + for bond_index in sorted(alchemical_region.alchemical_bonds): + [particle1, particle2, theta0, K] = reference_force.getBondParameters(bond_index) custom_force.addBond(particle1, particle2, [theta0, K]) + + # Update the returned value with the alchemical force. + alchemical_forces.update({lambda_variable_name: [custom_force]}) + + return alchemical_forces + + def _get_sterics_energy_expressions(self, lambda_variable_suffixes): + """Return the energy expressions for sterics. + + Parameters + ---------- + lambda_variable_suffixes : List[str] + A list with suffixes for the global variable "lambda_sterics" that + will control the energy. If no suffix is necessary (i.e. there are + no multiple alchemical regions) just set lambda_variable_suffixes[0] = ''. + If the list has more than one element, the energy is controlled by + the multiplication of lambda_sterics_suffix1 * lambda_sterics_suffix2. + """ + + # Sterics mixing rules. + if lambda_variable_suffixes[0] == '': + lambda_variable_name = 'lambda_sterics' + else: + if len(lambda_variable_suffixes) > 1: + lambda_variable_name = 'lambda_sterics{0}*lambda_sterics{1}'.format( + lambda_variable_suffixes[0], lambda_variable_suffixes[1]) else: - # Standard bond. - force.addBond(particle1, particle2, theta0, K) + lambda_variable_name = 'lambda_sterics{}'.format(lambda_variable_suffixes[0]) + + sterics_mixing_rules = ('epsilon = sqrt(epsilon1*epsilon2);' # Mixing rule for epsilon. + 'sigma = 0.5*(sigma1 + sigma2);') # Mixing rule for sigma. - return {'': [force], 'lambda_bonds': [custom_force]} + # Soft-core Lennard-Jones. + exceptions_sterics_energy_expression = ('U_sterics;' + 'U_sterics = (({0})^softcore_a)*4*epsilon*x*(x-1.0);' + 'x = (sigma/reff_sterics)^6;' + # Effective softcore distance for sterics. + 'reff_sterics = sigma*((softcore_alpha*(1.0-({0}))^softcore_b + (r/sigma)^softcore_c))^(1/softcore_c);')\ + .format(lambda_variable_name) + # Define energy expression for electrostatics. + return sterics_mixing_rules, exceptions_sterics_energy_expression - def _get_electrostatics_energy_expressions(self, reference_force): + def _get_electrostatics_energy_expressions(self, reference_force, lambda_variable_suffixes): """Return the energy expressions for electrostatics. This private function assumes self._alchemical_pme_treatment != 'exact' as there's no electrostatics CustomNondondedForce in this case, and lambda_electrostatics is modeled through an offset parameter in a NonbondedForce. + + Parameters + ---------- + lambda_variable_suffixes : List[str] + A list with suffixes for the global variable "lambda_electrostatics" that + will control the energy. If no suffix is necessary (i.e. there are + no multiple alchemical regions) just set lambda_variable_suffixes[0] = ''. + If the list has more than one element, the energy is controlled by + the multiplication of lambda_electrostatics_suffix1 * lambda_electrostatics_suffix2. """ + if lambda_variable_suffixes[0] == '': + lambda_variable_name = 'lambda_electrostatics' + else: + if len(lambda_variable_suffixes) > 1: + lambda_variable_name = 'lambda_electrostatics{0}*lambda_electrostatics{1}'.format( + lambda_variable_suffixes[0], lambda_variable_suffixes[1]) + else: + lambda_variable_name = 'lambda_electrostatics{}'.format(lambda_variable_suffixes[0]) # The final expression will be prefix + method + suffix. electrostatics_prefix = ('U_electrostatics;' - 'U_electrostatics=(lambda_electrostatics^softcore_d)*ONE_4PI_EPS0*chargeprod') + 'U_electrostatics=(({})^softcore_d)*ONE_4PI_EPS0*chargeprod').format(lambda_variable_name) # Effective softcore distance for electrostatics (common to all methods). - electrostatics_suffix = ('reff_electrostatics = sigma*((softcore_beta*(1.0-lambda_electrostatics)^softcore_e + (r/sigma)^softcore_f))^(1/softcore_f);' - 'ONE_4PI_EPS0 = {};').format(ONE_4PI_EPS0) # Already in OpenMM units. + electrostatics_suffix = ('reff_electrostatics = sigma*((softcore_beta*(1.0-({0}))^softcore_e + (r/sigma)^softcore_f))^(1/softcore_f);' + 'ONE_4PI_EPS0 = {1};').format(lambda_variable_name, ONE_4PI_EPS0) # Already in OpenMM units. # Define mixing rules. electrostatics_mixing_rules = ('chargeprod = charge1*charge2;' # Mixing rule for charges. @@ -1319,7 +1530,7 @@ def _get_pme_direct_space_unique_expression(self, reference_force): "alpha_ewald = {};").format(alpha_ewald) return pme_expression - def _alchemically_modify_NonbondedForce(self, reference_force, alchemical_region): + def _alchemically_modify_NonbondedForce(self, reference_force, alchemical_regions, alchemical_regions_interactions): """Create alchemically-modified version of NonbondedForce. Parameters @@ -1329,6 +1540,10 @@ def _alchemically_modify_NonbondedForce(self, reference_force, alchemical_region alchemical_region : AlchemicalRegion The alchemical region containing the indices of the atoms to alchemically modify. + alchemical_regions_interactions : Set[Tuple[int, int]], optional + Set of alchemical region index pairs for interacting regions. + By default, all alchemical regions interact only with the + non-alchemical environment. Returns ------- @@ -1365,27 +1580,25 @@ def _alchemically_modify_NonbondedForce(self, reference_force, alchemical_region # TODO Change softcore_beta to a dimensionless scalar to multiply some intrinsic length-scale, like Lennard-Jones alpha. # TODO Try using a single, common "reff" effective softcore distance for both Lennard-Jones and Coulomb. - # Don't create a force if there are no alchemical atoms. - if len(alchemical_region.alchemical_atoms) == 0: - return {'': [copy.deepcopy(reference_force)]} + forces_by_lambda = {} + all_alchemical_atoms = set() - # -------------------------------------------------- - # Determine energy expression for all custom forces - # -------------------------------------------------- + # Don't create a force if there are no alchemical atoms. + for alchemical_region in alchemical_regions: + if not len(alchemical_region.alchemical_atoms) == 0: + all_alchemical_atoms.update(alchemical_region.alchemical_atoms) - # Sterics mixing rules. - sterics_mixing_rules = ('epsilon = sqrt(epsilon1*epsilon2);' # Mixing rule for epsilon. - 'sigma = 0.5*(sigma1 + sigma2);') # Mixing rule for sigma. + # Don't create a force if there are no alchemical atoms. + if len(all_alchemical_atoms) == 0: + return {'': [copy.deepcopy(reference_force)]} - # Soft-core Lennard-Jones. - exceptions_sterics_energy_expression = ('U_sterics;' - 'U_sterics = (lambda_sterics^softcore_a)*4*epsilon*x*(x-1.0);' - 'x = (sigma/reff_sterics)^6;' - # Effective softcore distance for sterics. - 'reff_sterics = sigma*((softcore_alpha*(1.0-lambda_sterics)^softcore_b + (r/sigma)^softcore_c))^(1/softcore_c);') + # Create a set of all the non-alchemical atoms only. + all_atomset = set(range(reference_force.getNumParticles())) + nonalchemical_atomset = all_atomset.difference(all_alchemical_atoms) - # Define energy expression for sterics. - sterics_energy_expression = exceptions_sterics_energy_expression + sterics_mixing_rules + # ------------------------------------------------------------- + # Perform tasks that do not need to be repeated for all regions. + # ------------------------------------------------------------- # Define energy expression for electrostatics based on nonbonded method. nonbonded_method = reference_force.getNonbondedMethod() @@ -1403,309 +1616,429 @@ def _alchemically_modify_NonbondedForce(self, reference_force, alchemical_region # Check that PME treatment is supported with the region's parameters. if use_exact_pme_treatment: - err_msg = ' not supported with exact treatment of Ewald electrostatics.' - if not alchemical_region.annihilate_electrostatics: - raise ValueError('Decoupled electrostatics is' + err_msg) - if self.consistent_exceptions: - raise ValueError('Consistent exceptions are' + err_msg) - if (alchemical_region.softcore_beta, alchemical_region.softcore_d, alchemical_region.softcore_e) != (0, 1, 1): - raise ValueError('Softcore electrostatics is' + err_msg) - else: - # There's no CustomNonbondedForce that models electrostatics if we use exact - # PME treatment. Electrostatics is modeled through offset parameters. - energy_expressions = self._get_electrostatics_energy_expressions(reference_force) - (electrostatics_energy_expression, - exceptions_electrostatics_energy_expression) = energy_expressions # Unpack tuple. - - # ------------------------------------------------------------ - # Create and configure all forces to add to alchemical system - # ------------------------------------------------------------ - - # Interactions and exceptions will be distributed according to the following table. - - # -------------------------------------------------------------------------------------------------- - # FORCE | INTERACTION GROUP | - # -------------------------------------------------------------------------------------------------- - # nonbonded_force (unmodified) | all interactions nonalchemical/nonalchemical | - # | all exceptions nonalchemical/nonalchemical | - # -------------------------------------------------------------------------------------------------- - # aa_sterics_custom_nonbonded_force | sterics interactions alchemical/alchemical | - # -------------------------------------------------------------------------------------------------- - # aa_electrostatics_custom_nonbonded_force | electrostatics interactions alchemical/alchemical | - # | (only without exact PME treatment) | - # -------------------------------------------------------------------------------------------------- - # na_sterics_custom_nonbonded_force | sterics interactions non-alchemical/alchemical | - # -------------------------------------------------------------------------------------------------- - # na_electrostatics_custom_nonbonded_force | electrostatics interactions non-alchemical/alchemical | - # | (only without exact PME treatment) | - # -------------------------------------------------------------------------------------------------- - # aa_sterics_custom_bond_force | sterics exceptions alchemical/alchemical | - # -------------------------------------------------------------------------------------------------- - # aa_electrostatics_custom_bond_force | electrostatics exceptions alchemical/alchemical | - # | (only without exact PME treatment) | - # -------------------------------------------------------------------------------------------------- - # na_sterics_custom_bond_force | sterics exceptions non-alchemical/alchemical | - # -------------------------------------------------------------------------------------------------- - # na_electrostatics_custom_bond_force | electrostatics exceptions non-alchemical/alchemical | - # | (only without exact PME treatment) | - # -------------------------------------------------------------------------------------------------- + for alchemical_region in alchemical_regions: + err_msg = ' not supported with exact treatment of Ewald electrostatics.' + if not alchemical_region.annihilate_electrostatics: + raise ValueError('Decoupled electrostatics is' + err_msg) + if self.consistent_exceptions: + raise ValueError('Consistent exceptions are' + err_msg) + if (alchemical_region.softcore_beta, alchemical_region.softcore_d, alchemical_region.softcore_e) != (0, 1, 1): + raise ValueError('Softcore electrostatics is' + err_msg) # Create a copy of the NonbondedForce to handle particle interactions and # 1,4 exceptions between non-alchemical/non-alchemical atoms (nn). nonbonded_force = copy.deepcopy(reference_force) - def create_force(force_cls, energy_expression, lambda_variable_name, is_lambda_controlled): - """Shortcut to create a lambda-controlled custom forces.""" - if is_lambda_controlled: - force = force_cls(energy_expression) - force.addGlobalParameter(lambda_variable_name, 1.0) - else: # fix lambda variable to 1.0 - energy_expression = energy_expression + lambda_variable_name + '=1.0;' - force = force_cls(energy_expression) - return force - - # Create CustomNonbondedForces to handle sterics particle interactions between - # non-alchemical/alchemical atoms (na) and alchemical/alchemical atoms (aa). Fix lambda - # to 1.0 for decoupled interactions in alchemical/alchemical force. - na_sterics_custom_nonbonded_force = create_force(openmm.CustomNonbondedForce, sterics_energy_expression, - 'lambda_sterics', is_lambda_controlled=True) - aa_sterics_custom_nonbonded_force = create_force(openmm.CustomNonbondedForce, sterics_energy_expression, - 'lambda_sterics', alchemical_region.annihilate_sterics) - all_sterics_custom_nonbonded_forces = [na_sterics_custom_nonbonded_force, aa_sterics_custom_nonbonded_force] - - # Add parameters and configure CustomNonbondedForces to match reference force - for force in all_sterics_custom_nonbonded_forces: - force.addPerParticleParameter("sigma") # Lennard-Jones sigma - force.addPerParticleParameter("epsilon") # Lennard-Jones epsilon - force.setUseSwitchingFunction(nonbonded_force.getUseSwitchingFunction()) - force.setCutoffDistance(nonbonded_force.getCutoffDistance()) - force.setSwitchingDistance(nonbonded_force.getSwitchingDistance()) - if self.disable_alchemical_dispersion_correction: - force.setUseLongRangeCorrection(False) - else: - force.setUseLongRangeCorrection(nonbonded_force.getUseDispersionCorrection()) - - if is_periodic_method: - force.setNonbondedMethod(openmm.CustomNonbondedForce.CutoffPeriodic) - else: - force.setNonbondedMethod(nonbonded_force.getNonbondedMethod()) - - # With exact PME treatment, particle electrostatics is handled through offset parameters. - if use_exact_pme_treatment: - nonbonded_force.addGlobalParameter('lambda_electrostatics', 1.0) - all_electrostatics_custom_nonbonded_forces = [] - else: - # Create CustomNonbondedForces to handle electrostatics particle interactions between - # non-alchemical/alchemical atoms (na) and alchemical/alchemical atoms (aa). Fix lambda - # to 1.0 for decoupled interactions in alchemical/alchemical force. - na_electrostatics_custom_nonbonded_force = create_force(openmm.CustomNonbondedForce, electrostatics_energy_expression, - 'lambda_electrostatics', is_lambda_controlled=True) - aa_electrostatics_custom_nonbonded_force = create_force(openmm.CustomNonbondedForce, electrostatics_energy_expression, - 'lambda_electrostatics', alchemical_region.annihilate_electrostatics) - all_electrostatics_custom_nonbonded_forces = [na_electrostatics_custom_nonbonded_force, - aa_electrostatics_custom_nonbonded_force] - - # Common parameters and configuration for electrostatics CustomNonbondedForces. - for force in all_electrostatics_custom_nonbonded_forces: - force.addPerParticleParameter("charge") # partial charge - force.addPerParticleParameter("sigma") # Lennard-Jones sigma - if ((is_ewald_method and self.alchemical_pme_treatment == 'coulomb') or - (is_rf_method and self.alchemical_rf_treatment == 'switched')): - # Use switching function for alchemical electrostatics to ensure force continuity at cutoff. - force.setUseSwitchingFunction(True) - else: - force.setUseSwitchingFunction(False) - force.setSwitchingDistance(nonbonded_force.getCutoffDistance() - self.switch_width) - force.setCutoffDistance(nonbonded_force.getCutoffDistance()) - force.setUseLongRangeCorrection(False) # long-range dispersion correction is meaningless for electrostatics - - if is_periodic_method: - force.setNonbondedMethod(openmm.CustomNonbondedForce.CutoffPeriodic) - else: - force.setNonbondedMethod(nonbonded_force.getNonbondedMethod()) - - # Create CustomBondForces to handle sterics 1,4 exceptions interactions between - # non-alchemical/alchemical atoms (na) and alchemical/alchemical atoms (aa). Fix lambda - # to 1.0 for decoupled interactions in alchemical/alchemical force. - na_sterics_custom_bond_force = create_force(openmm.CustomBondForce, exceptions_sterics_energy_expression, - 'lambda_sterics', is_lambda_controlled=True) - aa_sterics_custom_bond_force = create_force(openmm.CustomBondForce, exceptions_sterics_energy_expression, - 'lambda_sterics', alchemical_region.annihilate_sterics) - all_sterics_custom_bond_forces = [na_sterics_custom_bond_force, aa_sterics_custom_bond_force] - - for force in all_sterics_custom_bond_forces: - force.addPerBondParameter("sigma") # Lennard-Jones effective sigma - force.addPerBondParameter("epsilon") # Lennard-Jones effective epsilon - - # With exact PME treatment, exception electrostatics is handled through offset parameters. - if use_exact_pme_treatment: - all_electrostatics_custom_bond_forces = [] - else: - # Create CustomBondForces to handle electrostatics 1,4 exceptions interactions between - # non-alchemical/alchemical atoms (na) and alchemical/alchemical atoms (aa). Fix lambda - # to 1.0 for decoupled interactions in alchemical/alchemical force. - na_electrostatics_custom_bond_force = create_force(openmm.CustomBondForce, exceptions_electrostatics_energy_expression, - 'lambda_electrostatics', is_lambda_controlled=True) - aa_electrostatics_custom_bond_force = create_force(openmm.CustomBondForce, exceptions_electrostatics_energy_expression, - 'lambda_electrostatics', alchemical_region.annihilate_electrostatics) - all_electrostatics_custom_bond_forces = [na_electrostatics_custom_bond_force, aa_electrostatics_custom_bond_force] - - # Create CustomBondForce to handle exceptions for electrostatics - for force in all_electrostatics_custom_bond_forces: - force.addPerBondParameter("chargeprod") # charge product - force.addPerBondParameter("sigma") # Lennard-Jones effective sigma - - # ------------------------------------------------------------------------------- - # Distribute particle interactions contributions in appropriate nonbonded forces - # ------------------------------------------------------------------------------- - - # Create atom groups. - alchemical_atomset = alchemical_region.alchemical_atoms - all_atomset = set(range(reference_force.getNumParticles())) # all atoms, including alchemical region - nonalchemical_atomset = all_atomset.difference(alchemical_atomset) - - # Fix any NonbondedForce issues with Lennard-Jones sigma = 0 (epsilon = 0), which should have sigma > 0. - for particle_index in range(nonbonded_force.getNumParticles()): + # Fix any issues in reference force with Lennard-Jones sigma = 0 (epsilon = 0), + # which should have sigma > 0. + for particle_index in range(reference_force.getNumParticles()): # Retrieve parameters. - [charge, sigma, epsilon] = nonbonded_force.getParticleParameters(particle_index) + [charge, sigma, epsilon] = reference_force.getParticleParameters(particle_index) # Check particle sigma is not zero. - if (sigma == 0.0 * unit.angstrom): + if sigma == 0.0 * unit.angstrom: warning_msg = 'particle %d has Lennard-Jones sigma = 0 (charge=%s, sigma=%s, epsilon=%s); setting sigma=1A' logger.warning(warning_msg % (particle_index, str(charge), str(sigma), str(epsilon))) sigma = 1.0 * unit.angstrom # Fix it. nonbonded_force.setParticleParameters(particle_index, charge, sigma, epsilon) - for exception_index in range(nonbonded_force.getNumExceptions()): + # Same for the exceptions. + for exception_index in range(reference_force.getNumExceptions()): # Retrieve parameters. - [iatom, jatom, chargeprod, sigma, epsilon] = nonbonded_force.getExceptionParameters(exception_index) + [iatom, jatom, chargeprod, sigma, epsilon] = reference_force.getExceptionParameters(exception_index) # Check particle sigma is not zero. - if (sigma == 0.0 * unit.angstrom): + if sigma == 0.0 * unit.angstrom: warning_msg = 'exception %d has Lennard-Jones sigma = 0 (iatom=%d, jatom=%d, chargeprod=%s, sigma=%s, epsilon=%s); setting sigma=1A' logger.warning(warning_msg % (exception_index, iatom, jatom, str(chargeprod), str(sigma), str(epsilon))) sigma = 1.0 * unit.angstrom # Fix it. nonbonded_force.setExceptionParameters(exception_index, iatom, jatom, chargeprod, sigma, epsilon) - # Copy NonbondedForce particle terms for alchemically-modified particles - # to CustomNonbondedForces, and/or add the charge offsets for exact PME. - # On CUDA, for efficiency reasons, all nonbonded forces (custom and not) - # must have the same particles. - for particle_index in range(nonbonded_force.getNumParticles()): - # Retrieve nonbonded parameters. - [charge, sigma, epsilon] = nonbonded_force.getParticleParameters(particle_index) - # Set sterics parameters in CustomNonbondedForces. + if use_exact_pme_treatment: + # Exclude noninteracting alchemical regions from seeing each other in the nonbonded + for x, y in itertools.combinations(range(len(alchemical_regions)), 2): + if (x, y) not in alchemical_regions_interactions: + for atom1 in alchemical_regions[x].alchemical_atoms: + for atom2 in alchemical_regions[y].alchemical_atoms: + nonbonded_force.addException(atom1, atom2, 0.0, 1.0, 0.0, True) + else: + region_names = (alchemical_regions[x].name, alchemical_regions[y].name) + logger.debug(f'Adding a exact PME electrostatic interaction group between groups {region_names}.') + del region_names + + # With exact PME treatment, particle electrostatics is handled through offset parameters. + for alchemical_region in alchemical_regions: + if alchemical_region.name is None: + nonbonded_force.addGlobalParameter('lambda_electrostatics', 1.0) + else: + nonbonded_force.addGlobalParameter(f'lambda_electrostatics_{alchemical_region.name}', 1.0) + + # Make of list of all single and double permutations of alchemical regions. + single_regions = [[alchemical_region] for alchemical_region in alchemical_regions] + if len(alchemical_regions_interactions) == 0: + pair_regions = [] + else: + # Only generate pairs of alchemical regions specified by alchemical_regions_interactions. + pair_regions = [[alchemical_regions[x[0]], alchemical_regions[x[1]]] for x in + alchemical_regions_interactions] + + # Iterate over all single and double permutations of alchemical regions to build all interactions. + for alchemical_regions_pairs in single_regions+pair_regions: + + # Make a list of region names for the alchemical regions interactions which are being built. + lambda_var_suffixes = [] + for alchemical_region in alchemical_regions_pairs: + if alchemical_region.name is None: + lambda_var_suffixes.append('') + else: + lambda_var_suffixes.append('_' + alchemical_region.name) + + # -------------------------------------------------- + # Determine energy expression for all custom forces + # -------------------------------------------------- + + # Get steric energy expressions. + sterics_mixing_rules, exceptions_sterics_energy_expression = self._get_sterics_energy_expressions(lambda_var_suffixes) + + # Define energy expression for sterics. + sterics_energy_expression = exceptions_sterics_energy_expression + sterics_mixing_rules + + if not use_exact_pme_treatment: + # There's no CustomNonbondedForce that models electrostatics if we use exact + # PME treatment. Electrostatics is modeled through offset parameters. + energy_expressions = self._get_electrostatics_energy_expressions(reference_force, lambda_var_suffixes) + (electrostatics_energy_expression, + exceptions_electrostatics_energy_expression) = energy_expressions # Unpack tuple. + + # ------------------------------------------------------------ + # Create and configure all forces to add to alchemical system + # ------------------------------------------------------------ + + # Interactions and exceptions will be distributed according to the following table. + + # -------------------------------------------------------------------------------------------------- + # FORCE | INTERACTION GROUP | + # -------------------------------------------------------------------------------------------------- + # nonbonded_force (unmodified) | all interactions nonalchemical/nonalchemical | + # | all exceptions nonalchemical/nonalchemical | + # -------------------------------------------------------------------------------------------------- + # aa_sterics_custom_nonbonded_force | sterics interactions alchemical/alchemical | + # -------------------------------------------------------------------------------------------------- + # aa_electrostatics_custom_nonbonded_force | electrostatics interactions alchemical/alchemical | + # | (only without exact PME treatment) | + # -------------------------------------------------------------------------------------------------- + # na_sterics_custom_nonbonded_force | sterics interactions non-alchemical/alchemical | + # -------------------------------------------------------------------------------------------------- + # na_electrostatics_custom_nonbonded_force | electrostatics interactions non-alchemical/alchemical | + # | (only without exact PME treatment) | + # -------------------------------------------------------------------------------------------------- + # aa_sterics_custom_bond_force | sterics exceptions alchemical/alchemical | + # -------------------------------------------------------------------------------------------------- + # aa_electrostatics_custom_bond_force | electrostatics exceptions alchemical/alchemical | + # | (only without exact PME treatment) | + # -------------------------------------------------------------------------------------------------- + # na_sterics_custom_bond_force | sterics exceptions non-alchemical/alchemical | + # -------------------------------------------------------------------------------------------------- + # na_electrostatics_custom_bond_force | electrostatics exceptions non-alchemical/alchemical | + # | (only without exact PME treatment) | + # -------------------------------------------------------------------------------------------------- + + def create_force(force_cls, energy_expression, lambda_variable_name, lambda_var_suffixes, is_lambda_controlled): + """Shortcut to create a lambda-controlled custom forces.""" + if is_lambda_controlled: + force = force_cls(energy_expression) + for suffix in lambda_var_suffixes: + name = (lambda_variable_name + suffix) + force.addGlobalParameter(name, 1.0) + else: # fix lambda variable to 1.0 + for suffix in lambda_var_suffixes: + name = (lambda_variable_name + suffix) + energy_expression = energy_expression + name + '=1.0;' + force = force_cls(energy_expression) + return force + + # Create CustomNonbondedForces to handle sterics particle interactions between + # non-alchemical/alchemical atoms (na) and alchemical/alchemical atoms (aa). Fix lambda + # to 1.0 for decoupled interactions in alchemical/alchemical force. + if len(lambda_var_suffixes) > 1: + aa_sterics_custom_nonbonded_force = create_force(openmm.CustomNonbondedForce, sterics_energy_expression, + 'lambda_sterics', lambda_var_suffixes, is_lambda_controlled=True) + all_sterics_custom_nonbonded_forces = [aa_sterics_custom_nonbonded_force] + else: + na_sterics_custom_nonbonded_force = create_force(openmm.CustomNonbondedForce, sterics_energy_expression, + 'lambda_sterics', lambda_var_suffixes, is_lambda_controlled=True) + aa_sterics_custom_nonbonded_force = create_force(openmm.CustomNonbondedForce, sterics_energy_expression, + 'lambda_sterics', lambda_var_suffixes, alchemical_region.annihilate_sterics) + all_sterics_custom_nonbonded_forces = [na_sterics_custom_nonbonded_force, aa_sterics_custom_nonbonded_force] + + # Add parameters and configure CustomNonbondedForces to match reference force. for force in all_sterics_custom_nonbonded_forces: - force.addParticle([sigma, epsilon]) - # Set electrostatics parameters in CustomNonbondedForces. + force.addPerParticleParameter("sigma") # Lennard-Jones sigma + force.addPerParticleParameter("epsilon") # Lennard-Jones epsilon + force.setUseSwitchingFunction(nonbonded_force.getUseSwitchingFunction()) + force.setCutoffDistance(nonbonded_force.getCutoffDistance()) + force.setSwitchingDistance(nonbonded_force.getSwitchingDistance()) + if self.disable_alchemical_dispersion_correction: + force.setUseLongRangeCorrection(False) + else: + force.setUseLongRangeCorrection(nonbonded_force.getUseDispersionCorrection()) + + if is_periodic_method: + force.setNonbondedMethod(openmm.CustomNonbondedForce.CutoffPeriodic) + else: + force.setNonbondedMethod(nonbonded_force.getNonbondedMethod()) + + if use_exact_pme_treatment: + #electrostatics are handled by offset + all_electrostatics_custom_nonbonded_forces = [] + else: + # Create CustomNonbondedForces to handle electrostatics particle interactions between + # non-alchemical/alchemical atoms (na) and alchemical/alchemical atoms (aa). Fix lambda + # to 1.0 for decoupled interactions in alchemical/alchemical force. + if len(lambda_var_suffixes) > 1: + aa_electrostatics_custom_nonbonded_force = create_force(openmm.CustomNonbondedForce, electrostatics_energy_expression, + 'lambda_electrostatics', lambda_var_suffixes, is_lambda_controlled=True) + all_electrostatics_custom_nonbonded_forces = [aa_electrostatics_custom_nonbonded_force] + else: + na_electrostatics_custom_nonbonded_force = create_force(openmm.CustomNonbondedForce, electrostatics_energy_expression, + 'lambda_electrostatics', lambda_var_suffixes, is_lambda_controlled=True) + aa_electrostatics_custom_nonbonded_force = create_force(openmm.CustomNonbondedForce, electrostatics_energy_expression, + 'lambda_electrostatics', lambda_var_suffixes, alchemical_region.annihilate_electrostatics) + all_electrostatics_custom_nonbonded_forces = [na_electrostatics_custom_nonbonded_force, + aa_electrostatics_custom_nonbonded_force] + + # Common parameters and configuration for electrostatics CustomNonbondedForces. for force in all_electrostatics_custom_nonbonded_forces: - force.addParticle([charge, sigma]) - # Set offset parameters in NonbondedForce. - if use_exact_pme_treatment and particle_index in alchemical_atomset: - nonbonded_force.addParticleParameterOffset('lambda_electrostatics', particle_index, - charge, 0.0, 0.0) - - # Turn off interactions contribution from alchemically-modified particles in unmodified - # NonbondedForce that will be handled by all other forces - for particle_index in range(nonbonded_force.getNumParticles()): - # Retrieve parameters. - [charge, sigma, epsilon] = nonbonded_force.getParticleParameters(particle_index) - # Even with exact treatment of the PME electrostatics, we turn off - # the NonbondedForce charge which is modeled by the offset parameter. - if particle_index in alchemical_atomset: - nonbonded_force.setParticleParameters(particle_index, abs(0.0*charge), sigma, abs(0*epsilon)) - - # Restrict interaction evaluation of CustomNonbondedForces to their respective atom groups. - na_sterics_custom_nonbonded_force.addInteractionGroup(nonalchemical_atomset, alchemical_atomset) - aa_sterics_custom_nonbonded_force.addInteractionGroup(alchemical_atomset, alchemical_atomset) - if not use_exact_pme_treatment: - na_electrostatics_custom_nonbonded_force.addInteractionGroup(nonalchemical_atomset, alchemical_atomset) - aa_electrostatics_custom_nonbonded_force.addInteractionGroup(alchemical_atomset, alchemical_atomset) - - # --------------------------------------------------------------- - # Distribute exceptions contributions in appropriate bond forces - # --------------------------------------------------------------- - - all_custom_nonbonded_forces = all_sterics_custom_nonbonded_forces + all_electrostatics_custom_nonbonded_forces - - # Move all NonbondedForce exception terms for alchemically-modified particles to CustomBondForces. - for exception_index in range(nonbonded_force.getNumExceptions()): - # Retrieve parameters. - [iatom, jatom, chargeprod, sigma, epsilon] = nonbonded_force.getExceptionParameters(exception_index) - - # Exclude this atom pair in CustomNonbondedForces. All nonbonded forces - # must have the same number of exceptions/exclusions on CUDA platform. - for force in all_custom_nonbonded_forces: - force.addExclusion(iatom, jatom) - - # Check how many alchemical atoms we have - both_alchemical = iatom in alchemical_atomset and jatom in alchemical_atomset - at_least_one_alchemical = iatom in alchemical_atomset or jatom in alchemical_atomset - only_one_alchemical = at_least_one_alchemical and not both_alchemical - - # Check if this is an exception or an exclusion - is_exception_epsilon = abs(epsilon.value_in_unit_system(unit.md_unit_system)) > 0.0 - is_exception_chargeprod = abs(chargeprod.value_in_unit_system(unit.md_unit_system)) > 0.0 - - # If this is an electrostatic exception and we're using exact PME, - # we just have to add the exception offset to the NonbondedForce. - if use_exact_pme_treatment and at_least_one_alchemical and is_exception_chargeprod: - nonbonded_force.addExceptionParameterOffset('lambda_electrostatics', exception_index, - chargeprod, 0.0, 0.0) - - # If exception (and not exclusion), add special CustomBondForce terms to - # handle alchemically-modified Lennard-Jones and electrostatics exceptions - if both_alchemical: - if is_exception_epsilon: - aa_sterics_custom_bond_force.addBond(iatom, jatom, [sigma, epsilon]) - if is_exception_chargeprod and not use_exact_pme_treatment: - aa_electrostatics_custom_bond_force.addBond(iatom, jatom, [chargeprod, sigma]) - elif only_one_alchemical: - if is_exception_epsilon: - na_sterics_custom_bond_force.addBond(iatom, jatom, [sigma, epsilon]) - if is_exception_chargeprod and not use_exact_pme_treatment: - na_electrostatics_custom_bond_force.addBond(iatom, jatom, [chargeprod, sigma]) - # else: both particles are non-alchemical, leave them in the unmodified NonbondedForce - - # Turn off all exception contributions from alchemical atoms in the NonbondedForce - # modelling non-alchemical atoms only - if at_least_one_alchemical: - nonbonded_force.setExceptionParameters(exception_index, iatom, jatom, - abs(0.0*chargeprod), sigma, abs(0.0*epsilon)) - - # Add global parameters to forces. - def add_global_parameters(force): - force.addGlobalParameter('softcore_alpha', alchemical_region.softcore_alpha) - force.addGlobalParameter('softcore_beta', alchemical_region.softcore_beta) - force.addGlobalParameter('softcore_a', alchemical_region.softcore_a) - force.addGlobalParameter('softcore_b', alchemical_region.softcore_b) - force.addGlobalParameter('softcore_c', alchemical_region.softcore_c) - force.addGlobalParameter('softcore_d', alchemical_region.softcore_d) - force.addGlobalParameter('softcore_e', alchemical_region.softcore_e) - force.addGlobalParameter('softcore_f', alchemical_region.softcore_f) - - all_custom_forces = (all_custom_nonbonded_forces + - all_sterics_custom_bond_forces + - all_electrostatics_custom_bond_forces) - for force in all_custom_forces: - add_global_parameters(force) - - # With exact treatment of PME electrostatics, the NonbondedForce - # is affected by lambda electrostatics as well. - forces_by_lambda = { - 'lambda_electrostatics': all_electrostatics_custom_nonbonded_forces + all_electrostatics_custom_bond_forces, - 'lambda_sterics': all_sterics_custom_nonbonded_forces + all_sterics_custom_bond_forces, - } + force.addPerParticleParameter("charge") # partial charge + force.addPerParticleParameter("sigma") # Lennard-Jones sigma + if ((is_ewald_method and self.alchemical_pme_treatment == 'coulomb') or + (is_rf_method and self.alchemical_rf_treatment == 'switched')): + # Use switching function for alchemical electrostatics to ensure force continuity at cutoff. + force.setUseSwitchingFunction(True) + else: + force.setUseSwitchingFunction(False) + force.setSwitchingDistance(nonbonded_force.getCutoffDistance() - self.switch_width) + force.setCutoffDistance(nonbonded_force.getCutoffDistance()) + force.setUseLongRangeCorrection(False) # long-range dispersion correction is meaningless for electrostatics + + if is_periodic_method: + force.setNonbondedMethod(openmm.CustomNonbondedForce.CutoffPeriodic) + else: + force.setNonbondedMethod(nonbonded_force.getNonbondedMethod()) + + # Create CustomBondForces to handle sterics 1,4 exceptions interactions between + # non-alchemical/alchemical atoms (na) and alchemical/alchemical atoms (aa). Fix lambda + # to 1.0 for decoupled interactions in alchemical/alchemical force. + if len(lambda_var_suffixes) > 1: + aa_sterics_custom_bond_force = create_force(openmm.CustomBondForce, exceptions_sterics_energy_expression, + 'lambda_sterics', lambda_var_suffixes, is_lambda_controlled=True) + all_sterics_custom_bond_forces = [aa_sterics_custom_bond_force] + else: + na_sterics_custom_bond_force = create_force(openmm.CustomBondForce, exceptions_sterics_energy_expression, + 'lambda_sterics', lambda_var_suffixes, is_lambda_controlled=True) + aa_sterics_custom_bond_force = create_force(openmm.CustomBondForce, exceptions_sterics_energy_expression, + 'lambda_sterics', lambda_var_suffixes, alchemical_region.annihilate_sterics) + all_sterics_custom_bond_forces = [na_sterics_custom_bond_force, aa_sterics_custom_bond_force] + + for force in all_sterics_custom_bond_forces: + force.addPerBondParameter("sigma") # Lennard-Jones effective sigma + force.addPerBondParameter("epsilon") # Lennard-Jones effective epsilon + + # With exact PME treatment, exception electrostatics is handled through offset parameters. + if use_exact_pme_treatment: + all_electrostatics_custom_bond_forces = [] + else: + # Create CustomBondForces to handle electrostatics 1,4 exceptions interactions between + # non-alchemical/alchemical atoms (na) and alchemical/alchemical atoms (aa). Fix lambda + # to 1.0 for decoupled interactions in alchemical/alchemical force. + if len(lambda_var_suffixes) > 1: + aa_electrostatics_custom_bond_force = create_force(openmm.CustomBondForce, exceptions_electrostatics_energy_expression, + 'lambda_electrostatics', lambda_var_suffixes, is_lambda_controlled=True) + all_electrostatics_custom_bond_forces = [aa_electrostatics_custom_bond_force] + else: + na_electrostatics_custom_bond_force = create_force(openmm.CustomBondForce, exceptions_electrostatics_energy_expression, + 'lambda_electrostatics', lambda_var_suffixes, is_lambda_controlled=True) + aa_electrostatics_custom_bond_force = create_force(openmm.CustomBondForce, exceptions_electrostatics_energy_expression, + 'lambda_electrostatics', lambda_var_suffixes, alchemical_region.annihilate_electrostatics) + all_electrostatics_custom_bond_forces = [na_electrostatics_custom_bond_force, aa_electrostatics_custom_bond_force] + + # Create CustomBondForce to handle exceptions for electrostatics + for force in all_electrostatics_custom_bond_forces: + force.addPerBondParameter("chargeprod") # charge product + force.addPerBondParameter("sigma") # Lennard-Jones effective sigma + + # ------------------------------------------------------------------------------- + # Distribute particle interactions contributions in appropriate nonbonded forces + # ------------------------------------------------------------------------------- + + # Create atom groups. + alchemical_atomsets = [region.alchemical_atoms for region in alchemical_regions_pairs] + + # Copy NonbondedForce particle terms for alchemically-modified particles + # to CustomNonbondedForces, and/or add the charge offsets for exact PME. + # On CUDA, for efficiency reasons, all nonbonded forces (custom and not) + # must have the same particles. + for particle_index in range(nonbonded_force.getNumParticles()): + # Retrieve nonbonded parameters. + [charge, sigma, epsilon] = nonbonded_force.getParticleParameters(particle_index) + # Set sterics parameters in CustomNonbondedForces. + for force in all_sterics_custom_nonbonded_forces: + force.addParticle([sigma, epsilon]) + # Set electrostatics parameters in CustomNonbondedForces. + for force in all_electrostatics_custom_nonbonded_forces: + force.addParticle([charge, sigma]) + # Set offset parameters in NonbondedForce. + if use_exact_pme_treatment and particle_index in alchemical_atomsets[0] and len(lambda_var_suffixes) == 1: + nonbonded_force.addParticleParameterOffset('lambda_electrostatics{}'.format(lambda_var_suffixes[0]), + particle_index, charge, 0.0, 0.0) + + # Turn off interactions contribution from alchemically-modified particles in unmodified + # NonbondedForce that will be handled by all other forces + for particle_index in range(nonbonded_force.getNumParticles()): + # Retrieve parameters. + [charge, sigma, epsilon] = nonbonded_force.getParticleParameters(particle_index) + # Even with exact treatment of the PME electrostatics, we turn off + # the NonbondedForce charge which is modeled by the offset parameter. + if particle_index in alchemical_atomsets[0]: + nonbonded_force.setParticleParameters(particle_index, abs(0.0*charge), sigma, abs(0*epsilon)) + + # Restrict interaction evaluation of CustomNonbondedForces to their respective atom groups. + # Sterics + if len(lambda_var_suffixes) == 1: + logger.debug('Adding steric interaction groups between {} and the environment.'.format(lambda_var_suffixes[0])) + na_sterics_custom_nonbonded_force.addInteractionGroup(nonalchemical_atomset, alchemical_atomsets[0]) + + logger.debug('Adding a steric interaction group between group {0} and {1}.'.format(lambda_var_suffixes[0], + lambda_var_suffixes[-1])) + aa_sterics_custom_nonbonded_force.addInteractionGroup(alchemical_atomsets[0], alchemical_atomsets[-1]) + + # Electrostatics + if not use_exact_pme_treatment: + if len(lambda_var_suffixes) == 1: + logger.debug('Adding electrostatic interaction groups between {} and the environment.'.format(lambda_var_suffixes[0])) + na_electrostatics_custom_nonbonded_force.addInteractionGroup(nonalchemical_atomset, alchemical_atomsets[0]) + + logger.debug('Adding a electrostatic interaction group between group {0} and {1}.'.format(lambda_var_suffixes[0], + lambda_var_suffixes[-1])) + aa_electrostatics_custom_nonbonded_force.addInteractionGroup(alchemical_atomsets[0], alchemical_atomsets[-1]) + + else: + # Using the nonbonded force to handle electrostatics + # and the "interaction groups" in the nonbonded have already been handled by exclusions. + pass + + # --------------------------------------------------------------- + # Distribute exceptions contributions in appropriate bond forces + # --------------------------------------------------------------- + + all_custom_nonbonded_forces = all_sterics_custom_nonbonded_forces + all_electrostatics_custom_nonbonded_forces + + # Move all NonbondedForce exception terms for alchemically-modified particles to CustomBondForces. + for exception_index in range(nonbonded_force.getNumExceptions()): + # Retrieve parameters. + iatom, jatom, chargeprod, sigma, epsilon = nonbonded_force.getExceptionParameters(exception_index) + + # Exclude this atom pair in CustomNonbondedForces. All nonbonded forces + # must have the same number of exceptions/exclusions on CUDA platform. + for force in all_custom_nonbonded_forces: + force.addExclusion(iatom, jatom) + + # Check if this is an exception or an exclusion + is_exception_epsilon = abs(epsilon.value_in_unit_system(unit.md_unit_system)) > 0.0 + is_exception_chargeprod = abs(chargeprod.value_in_unit_system(unit.md_unit_system)) > 0.0 + + # Check how many alchemical atoms we have in the exception. + if len(lambda_var_suffixes) > 1: + # Pair of interacting alchemical regions, therefore they are both alchemical or neither alchemical. + both_alchemical = ((iatom in alchemical_atomsets[0] and jatom in alchemical_atomsets[1]) or + (jatom in alchemical_atomsets[0] and iatom in alchemical_atomsets[1])) + only_one_alchemical = False + #The condition of at_least_one_alchemical is treated only once per single + # region so we don't repeat it when dealing with pairs of interacting regions. + at_least_one_alchemical = False + + + if use_exact_pme_treatment and both_alchemical and is_exception_chargeprod: + # Exceptions here should be scaled by lam0*lam1. + # This can be implemented in the future using a CustomBondForce. + raise ValueError('Cannot have exception that straddles two alchemical regions') + + else: + # Single alchemical region. + both_alchemical = iatom in alchemical_atomsets[0] and jatom in alchemical_atomsets[0] + at_least_one_alchemical = iatom in alchemical_atomsets[0] or jatom in alchemical_atomsets[0] + only_one_alchemical = at_least_one_alchemical and not both_alchemical + + # If this is an electrostatic exception and we're using exact PME, + # we just have to add the exception offset to the NonbondedForce. + if use_exact_pme_treatment and at_least_one_alchemical and is_exception_chargeprod: + nonbonded_force.addExceptionParameterOffset('lambda_electrostatics{}'.format(lambda_var_suffixes[0]), + exception_index, chargeprod, 0.0, 0.0) + + # If exception (and not exclusion), add special CustomBondForce terms to + # handle alchemically-modified Lennard-Jones and electrostatics exceptions + if both_alchemical: + if is_exception_epsilon: + aa_sterics_custom_bond_force.addBond(iatom, jatom, [sigma, epsilon]) + if is_exception_chargeprod and not use_exact_pme_treatment: + aa_electrostatics_custom_bond_force.addBond(iatom, jatom, [chargeprod, sigma]) + + # When this is a single region we model the exception between alchemical + # and non-alchemical particles using a single custom bond. + elif only_one_alchemical: + if is_exception_epsilon: + na_sterics_custom_bond_force.addBond(iatom, jatom, [sigma, epsilon]) + if is_exception_chargeprod and not use_exact_pme_treatment: + na_electrostatics_custom_bond_force.addBond(iatom, jatom, [chargeprod, sigma]) + # else: both particles are non-alchemical, leave them in the unmodified NonbondedForce + + # Turn off all exception contributions from alchemical atoms in the NonbondedForce + # modelling non-alchemical atoms only. We need to do it only once per single + # region so we don't repeat it when dealing with pairs of interacting regions. + if at_least_one_alchemical: + nonbonded_force.setExceptionParameters(exception_index, iatom, jatom, + abs(0.0*chargeprod), sigma, abs(0.0*epsilon)) + + # Add global parameters to forces. + def add_global_parameters(force): + force.addGlobalParameter('softcore_alpha', alchemical_region.softcore_alpha) + force.addGlobalParameter('softcore_beta', alchemical_region.softcore_beta) + force.addGlobalParameter('softcore_a', alchemical_region.softcore_a) + force.addGlobalParameter('softcore_b', alchemical_region.softcore_b) + force.addGlobalParameter('softcore_c', alchemical_region.softcore_c) + force.addGlobalParameter('softcore_d', alchemical_region.softcore_d) + force.addGlobalParameter('softcore_e', alchemical_region.softcore_e) + force.addGlobalParameter('softcore_f', alchemical_region.softcore_f) + + all_custom_forces = (all_custom_nonbonded_forces + + all_sterics_custom_bond_forces + + all_electrostatics_custom_bond_forces) + for force in all_custom_forces: + add_global_parameters(force) + + # With exact treatment of PME electrostatics, the NonbondedForce + # is affected by lambda electrostatics as well. + if 'lambda_sterics{}'.format(lambda_var_suffixes[0]) in forces_by_lambda: + forces_by_lambda['lambda_electrostatics{}'.format(lambda_var_suffixes[0])].extend(all_electrostatics_custom_nonbonded_forces + all_electrostatics_custom_bond_forces) + forces_by_lambda['lambda_sterics{}'.format(lambda_var_suffixes[0])].extend(all_sterics_custom_nonbonded_forces + all_sterics_custom_bond_forces) + else: + forces_by_lambda['lambda_electrostatics{}'.format(lambda_var_suffixes[0])] = all_electrostatics_custom_nonbonded_forces + all_electrostatics_custom_bond_forces + forces_by_lambda['lambda_sterics{}'.format(lambda_var_suffixes[0])] = all_sterics_custom_nonbonded_forces + all_sterics_custom_bond_forces + if use_exact_pme_treatment: - forces_by_lambda['lambda_electrostatics'].append(nonbonded_force) + forces_by_lambda['lambda_electrostatics{}'.format(lambda_var_suffixes[0])].append(nonbonded_force) else: forces_by_lambda[''] = [nonbonded_force] return forces_by_lambda - def _alchemically_modify_AmoebaMultipoleForce(self, reference_force, alchemical_region): + def _alchemically_modify_AmoebaMultipoleForce(self, reference_force, alchemical_region, _): + if len(alchemical_region) > 1: + raise NotImplementedError("Multiple regions does not work with AmoebaMultipoleForce") + else: + alchemical_region = alchemical_region[0] raise Exception("Not implemented; needs CustomMultipleForce") - def _alchemically_modify_AmoebaVdwForce(self, reference_force, alchemical_region): + def _alchemically_modify_AmoebaVdwForce(self, reference_force, alchemical_region, _): """Create alchemically-modified version of AmoebaVdwForce. Not implemented. @@ -1717,7 +2050,11 @@ def _alchemically_modify_AmoebaVdwForce(self, reference_force, alchemical_region """ # This feature is incompletely implemented, so raise an exception. - raise NotImplemented('Alchemical modification of Amoeba VdW Forces is not supported.') + if len(alchemical_region) > 1: + raise NotImplementedError("Multiple regions does not work with AmoebaVdwForce") + else: + alchemical_region = alchemical_region[0] + raise NotImplementedError('Alchemical modification of Amoeba VdW Forces is not supported.') # Softcore Halgren potential from Eq. 3 of # Shi, Y., Jiao, D., Schnieders, M.J., and Ren, P. (2009). Trypsin-ligand binding free @@ -1767,7 +2104,7 @@ def _alchemically_modify_AmoebaVdwForce(self, reference_force, alchemical_region return [softcore_force] @staticmethod - def _alchemically_modify_GBSAOBCForce(reference_force, alchemical_region, sasa_model='ACE'): + def _alchemically_modify_GBSAOBCForce(reference_force, alchemical_region, _, sasa_model='ACE'): """Create alchemically-modified version of GBSAOBCForce. Parameters @@ -1791,6 +2128,11 @@ def _alchemically_modify_GBSAOBCForce(reference_force, alchemical_region, sasa_m * Can we more generally modify any CustomGBSAForce? """ + if len(alchemical_region) > 1: + raise NotImplementedError("Multiple regions does not work with GBSAOBCForce") + else: + alchemical_region = alchemical_region[0] + # TODO make sasa_model a Factory attribute? custom_force = openmm.CustomGBForce() @@ -1841,7 +2183,7 @@ def _alchemically_modify_GBSAOBCForce(reference_force, alchemical_region, sasa_m return {'lambda_electrostatics': [custom_force]} - def _alchemically_modify_CustomGBForce(self, reference_force, alchemical_region): + def _alchemically_modify_CustomGBForce(self, reference_force, alchemical_region, _): """Create alchemically-modified version of CustomGBForce. The GB functions are meta-programmed using the following rules: @@ -1880,6 +2222,11 @@ def _alchemically_modify_CustomGBForce(self, reference_force, alchemical_region) The alchemical version of the reference force. """ + if len(alchemical_region) > 1: + raise NotImplementedError("Multiple regions does not work with CustomGBForce") + else: + alchemical_region = alchemical_region[0] + custom_force = openmm.CustomGBForce() # Add global parameters @@ -1969,13 +2316,14 @@ def add_label(label, index): def check_parameter(custom_force, parameter): for parameter_id in range(custom_force.getNumGlobalParameters()): parameter_name = custom_force.getGlobalParameterName(parameter_id) - if parameter == parameter_name: - return True - return False + if parameter_name.startswith(parameter): + region_name = parameter_name[len(parameter)+1:] if len(parameter_name) > len(parameter) else None + return [True, region_name] + return [False, None] def check_energy_expression(custom_force, parameter): try: - found = parameter in custom_force.getEnergyFunction() + energy_expression = custom_force.getEnergyFunction() except AttributeError: # CustomGBForce found = False for index in range(custom_force.getNumEnergyTerms()): @@ -1983,92 +2331,174 @@ def check_energy_expression(custom_force, parameter): if parameter in expression: found = True break - return found + return [found, ''] # CustomGBForce will not have a parameter suffix + found = parameter in energy_expression + if not found: + return [found, ''] # param not found and by extension no parameter suffix + #Look for parameter suffix + p = re.compile(r'{}_([A-Za-z0-9]+)'.format(parameter)) + try: + suffix = p.search(energy_expression).group(1) + return [found, suffix] + except AttributeError: + return [found, ''] # no parameter suffix found force_labels = {} - nonbonded_forces = [] - sterics_bond_forces = [] - electro_bond_forces = [] + nonbonded_forces = {} + sterics_bond_forces = {} + electro_bond_forces = {} # We save CustomBondForces and CustomNonbondedForces used for nonbonded # forces and exceptions to distinguish them later for force_index, force in enumerate(alchemical_system.getForces()): - if isinstance(force, openmm.CustomAngleForce) and check_parameter(force, 'lambda_angles'): - add_label('alchemically modified HarmonicAngleForce', force_index) - elif isinstance(force, openmm.CustomBondForce) and check_parameter(force, 'lambda_bonds'): - add_label('alchemically modified HarmonicBondForce', force_index) - elif isinstance(force, openmm.CustomTorsionForce) and check_parameter(force, 'lambda_torsions'): - add_label('alchemically modified PeriodicTorsionForce', force_index) - elif isinstance(force, openmm.CustomGBForce) and check_parameter(force, 'lambda_electrostatics'): - if check_energy_expression(force, 'unscaled'): - add_label('alchemically modified CustomGBForce', force_index) - else: - add_label('alchemically modified GBSAOBCForce', force_index) - elif isinstance(force, openmm.CustomBondForce) and check_energy_expression(force, 'lambda'): - if check_energy_expression(force, 'lambda_sterics'): - sterics_bond_forces.append([force_index, force]) - else: - electro_bond_forces.append([force_index, force]) + if isinstance(force, openmm.CustomAngleForce): + parameter_found, region_name = check_parameter(force, 'lambda_angles') + if parameter_found: + label = 'alchemically modified HarmonicAngleForce' + if region_name is not None: + label = label + ' for region ' + region_name + add_label(label, force_index) + + elif isinstance(force, openmm.CustomBondForce) and check_parameter(force, 'lambda_bonds')[0]: + #Need extra check for 'lambda_bonds' in the if to differntiate from exceptions + parameter_found, region_name = check_parameter(force, 'lambda_bonds') + if parameter_found: + label = 'alchemically modified HarmonicBondForce' + if region_name is not None: + label = label + ' for region ' + region_name + add_label(label, force_index) + + elif isinstance(force, openmm.CustomTorsionForce): + parameter_found, region_name = check_parameter(force, 'lambda_torsions') + if parameter_found: + label = 'alchemically modified PeriodicTorsionForce' + if region_name is not None: + label = label + ' for region ' + region_name + add_label(label, force_index) + + elif isinstance(force, openmm.CustomGBForce): + parameter_found, _ = check_parameter(force, 'lambda_electrostatics') + if parameter_found: + #No multi region for GBForce + if check_energy_expression(force, 'unscaled')[0]: + add_label('alchemically modified CustomGBForce', force_index) + else: + add_label('alchemically modified GBSAOBCForce', force_index) + + elif isinstance(force, openmm.CustomBondForce): + parameter_found, region_type_suffix = check_energy_expression(force, 'lambda') + if parameter_found: + _, region_name_suffix = check_energy_expression(force, 'lambda_{}'.format(region_type_suffix)) + if region_type_suffix == 'sterics': + if region_name_suffix in sterics_bond_forces: + sterics_bond_forces[region_name_suffix].append([force_index, force]) + else: + sterics_bond_forces[region_name_suffix] = [[force_index, force]] + if region_type_suffix == 'electrostatics': + if region_name_suffix in electro_bond_forces: + electro_bond_forces[region_name_suffix].append([force_index, force]) + else: + electro_bond_forces[region_name_suffix] = [[force_index, force]] + elif (isinstance(force, openmm.CustomNonbondedForce) and force.getEnergyFunction() == '0.0;' and force.getGlobalParameterName(0) == 'lambda_electrostatics'): add_label('CustomNonbondedForce holding alchemical atoms unmodified charges', force_index) - elif isinstance(force, openmm.CustomNonbondedForce) and check_energy_expression(force, 'lambda'): - if check_energy_expression(force, 'lambda_sterics'): - nonbonded_forces.append(['sterics', force_index, force]) - else: - nonbonded_forces.append(['electrostatics', force_index, force]) + + elif isinstance(force, openmm.CustomNonbondedForce): + parameter_found, region_type_suffix = check_energy_expression(force, 'lambda') + if parameter_found: + _, region_name_suffix = check_energy_expression(force, 'lambda_{}'.format(region_type_suffix)) + if region_type_suffix == 'sterics': + if region_name_suffix in nonbonded_forces: + nonbonded_forces[region_name_suffix].append(['sterics', force_index, force]) + else: + nonbonded_forces[region_name_suffix] = [['sterics', force_index, force]] + if region_type_suffix == 'electrostatics': + if region_name_suffix in nonbonded_forces: + nonbonded_forces[region_name_suffix].append(['electrostatics', force_index, force]) + else: + nonbonded_forces[region_name_suffix] = [['electrostatics', force_index, force]] else: add_label('unmodified ' + force.__class__.__name__, force_index) # Differentiate between na/aa nonbonded forces. - for force_type, force_index, force in nonbonded_forces: - label = 'alchemically modified NonbondedForce for {}alchemical/alchemical ' + force_type - interacting_atoms, alchemical_atoms = force.getInteractionGroupParameters(0) - if interacting_atoms == alchemical_atoms: # alchemical-alchemical atoms - add_label(label.format(''), force_index) + alchemical_atoms_by_region = {} + for region_name, forces in nonbonded_forces.items(): + for force_type, force_index, force in forces: + if region_name == '': + label = 'alchemically modified NonbondedForce for {}alchemical/alchemical ' + force_type + else: + label = 'alchemically modified NonbondedForce for {}alchemical/alchemical ' + force_type +\ + ' for region ' + region_name + interacting_atoms, alchemical_atoms = force.getInteractionGroupParameters(0) + alchemical_atoms_by_region[region_name] = [interacting_atoms, alchemical_atoms] + if interacting_atoms == alchemical_atoms: # alchemical-alchemical atoms + add_label(label.format(''), force_index) + else: + add_label(label.format('non-'), force_index) + + # Initialize sterics_bond_forces or electro_bond_forces for regions which did not have forces, as empty lists + for k in sterics_bond_forces.keys(): + if k in electro_bond_forces: + pass else: - add_label(label.format('non-'), force_index) + electro_bond_forces[k] = [] + for k in electro_bond_forces.keys(): + if k in sterics_bond_forces: + pass + else: + sterics_bond_forces[k] = [] # Differentiate between na/aa bond forces for exceptions. - for force_type, bond_forces in [('sterics', sterics_bond_forces), ('electrostatics', electro_bond_forces)]: - # With exact PME there are no CustomBondForces modeling electrostatics exceptions. - if force_type == 'electrostatics' and len(bond_forces) == 0: + for (region_name, sterics_forces), electro_forces in zip(sterics_bond_forces.items(), electro_bond_forces.values()): + if len(sterics_forces) == 0: continue - # Otherwise there should be two CustomBondForce. - assert len(bond_forces) == 2 - label = 'alchemically modified BondForce for {}alchemical/alchemical ' + force_type + ' exceptions' - - # Sort forces by number of bonds. - bond_forces = sorted(bond_forces, key=lambda x: x[1].getNumBonds()) - (force_index1, force1), (force_index2, force2) = bond_forces - - # Check if both define their parameters (with decoupling the lambda - # parameter doesn't exist in the alchemical-alchemical force) - parameter_name = 'lambda_' + force_type - if check_parameter(force1, parameter_name) != check_parameter(force2, parameter_name): - if check_parameter(force1, parameter_name): - add_label(label.format('non-'), force_index1) - add_label(label.format(''), force_index2) + for force_type, bond_forces in [('sterics', sterics_forces), ('electrostatics', electro_forces)]: + # With exact PME there are no CustomBondForces modeling electrostatics exceptions. + if force_type == 'electrostatics' and len(bond_forces) == 0: + continue + # Otherwise there should be two CustomBondForce. + assert len(bond_forces) == 2 + if region_name == '': + label = 'alchemically modified BondForce for {}alchemical/alchemical ' + force_type + ' exceptions' else: + label = 'alchemically modified BondForce for {}alchemical/alchemical ' + force_type +\ + ' exceptions for region ' + region_name + + # Sort forces by number of bonds. + bond_forces = sorted(bond_forces, key=lambda x: x[1].getNumBonds()) + (force_index1, force1), (force_index2, force2) = bond_forces + + # Check if both define their parameters (with decoupling the lambda + # parameter doesn't exist in the alchemical-alchemical force) + parameter_name = 'lambda_' + force_type + if region_name != '': + parameter_name = parameter_name + '_{}'.format(region_name) + interacting_atoms, alchemical_atoms = alchemical_atoms_by_region[region_name] + + if check_parameter(force1, parameter_name)[0] != check_parameter(force2, parameter_name)[0]: + if check_parameter(force1, parameter_name)[0]: + add_label(label.format('non-'), force_index1) + add_label(label.format(''), force_index2) + else: + add_label(label.format(''), force_index1) + add_label(label.format('non-'), force_index2) + + # If they are both empty they are identical and any label works. + elif force1.getNumBonds() == 0 and force2.getNumBonds() == 0: add_label(label.format(''), force_index1) add_label(label.format('non-'), force_index2) - # If they are both empty they are identical and any label works. - elif force1.getNumBonds() == 0 and force2.getNumBonds() == 0: - add_label(label.format(''), force_index1) - add_label(label.format('non-'), force_index2) - - # We check that the bond atoms are both alchemical or not. - else: - atom_i, atom_j, _ = force2.getBondParameters(0) - both_alchemical = atom_i in alchemical_atoms and atom_j in alchemical_atoms - if both_alchemical: - add_label(label.format(''), force_index2) - add_label(label.format('non-'), force_index1) + # We check that the bond atoms are both alchemical or not. else: - add_label(label.format('non-'), force_index2) - add_label(label.format(''), force_index1) - + atom_i, atom_j, _ = force2.getBondParameters(0) + both_alchemical = atom_i in alchemical_atoms and atom_j in alchemical_atoms + if both_alchemical: + add_label(label.format(''), force_index2) + add_label(label.format('non-'), force_index1) + else: + add_label(label.format('non-'), force_index2) + add_label(label.format(''), force_index1) return force_labels diff --git a/openmmtools/cache.py b/openmmtools/cache.py index 346ee2549..619e45530 100644 --- a/openmmtools/cache.py +++ b/openmmtools/cache.py @@ -229,6 +229,9 @@ class ContextCache(object): platform : simtk.openmm.Platform, optional The OpenMM platform to use to create Contexts. If None, OpenMM tries to select the fastest one available (default is None). + platform_properties : dict, optional + A dictionary of platform properties for the OpenMM platform. + Only valid if the platform is not None (default is None). **kwargs Parameters to pass to the underlying LRUCache constructor such as capacity and time_to_live. @@ -303,8 +306,10 @@ class ContextCache(object): """ - def __init__(self, platform=None, **kwargs): + def __init__(self, platform=None, platform_properties=None, **kwargs): + self._validate_platform_properties(platform, platform_properties) self._platform = platform + self._platform_properties = platform_properties self._lru = LRUCache(**kwargs) def __len__(self): @@ -324,8 +329,18 @@ def platform(self): def platform(self, new_platform): if len(self._lru) > 0: raise RuntimeError('Cannot change platform of a non-empty ContextCache') + if new_platform is None: + self._platform_properties = None + self._validate_platform_properties(new_platform, self._platform_properties) self._platform = new_platform + def set_platform(self, new_platform, platform_properties=None): + if len(self._lru) > 0: + raise RuntimeError('Cannot change platform of a non-empty ContextCache') + self._validate_platform_properties(new_platform, platform_properties) + self._platform = new_platform + self._platform_properties = platform_properties + @property def capacity(self): """The maximum number of Context cached. @@ -429,7 +444,7 @@ def get_context(self, thermodynamic_state, integrator=None): try: context = self._lru[context_id] except KeyError: - context = thermodynamic_state.create_context(integrator, self._platform) + context = thermodynamic_state.create_context(integrator, self._platform, self._platform_properties) self._lru[context_id] = context context_integrator = context.getIntegrator() @@ -442,18 +457,24 @@ def get_context(self, thermodynamic_state, integrator=None): return context, context_integrator def __getstate__(self): + # this serialization format was introduced in openmmtools > 0.18.3 (pull request #437) if self.platform is not None: platform_serialization = self.platform.getName() else: platform_serialization = None return dict(platform=platform_serialization, capacity=self.capacity, - time_to_live=self.time_to_live) + time_to_live=self.time_to_live, platform_properties=self._platform_properties) def __setstate__(self, serialization): + # this serialization format was introduced in openmmtools > 0.18.3 (pull request #437) if serialization['platform'] is None: self._platform = None else: self._platform = openmm.Platform.getPlatformByName(serialization['platform']) + if not 'platform_properties' in serialization: + self._platform_properties = None + else: + self._platform_properties = serialization["platform_properties"] self._lru = LRUCache(serialization['capacity'], serialization['time_to_live']) # ------------------------------------------------------------------------- @@ -630,6 +651,35 @@ def _default_integrator_id(cls): return cls._cached_default_integrator_id _cached_default_integrator_id = None + @staticmethod + def _validate_platform_properties(platform=None, platform_properties=None): + """Check if platform properties are valid for the platform; else raise ValueError.""" + if platform_properties is None: + return True + if platform_properties is not None and platform is None: + raise ValueError("To set platform_properties, you need to also specify the platform.") + if not isinstance(platform_properties, dict): + raise ValueError("platform_properties must be a dictionary") + for key, value in platform_properties.items(): + if not isinstance(value, str): + raise ValueError( + "All platform properties must be strings. You supplied {}: {} of type {}".format( + key, value, type(value) + ) + ) + # create a context to check if all properties are + dummy_system = openmm.System() + dummy_system.addParticle(1) + dummy_integrator = openmm.VerletIntegrator(1.0*unit.femtoseconds) + try: + openmm.Context(dummy_system, dummy_integrator, platform, platform_properties) + return True + except Exception as e: + if "Illegal property name" in str(e): + raise ValueError("Invalid platform property for this platform. {}".format(e)) + else: + raise e + # ============================================================================= # DUMMY CONTEXT CACHE @@ -650,12 +700,57 @@ class DummyContextCache(object): The OpenMM platform to use. If None, OpenMM tries to select the fastest one available. + Examples + -------- + Create a new ``Context`` object for alanine dipeptide in vacuum in NPT. + + >>> from simtk import openmm, unit + >>> from openmmtools import states, testsystems + >>> system = testsystems.AlanineDipeptideVacuum().system + >>> thermo_state = states.ThermodynamicState(system, temperature=300*unit.kelvin) + + >>> context_cache = DummyContextCache() + >>> integrator = openmm.VerletIntegrator(1.0*unit.femtosecond) + >>> context, context_integrator = context_cache.get_context(thermo_state, integrator) + + Or create a ``Context`` with an arbitrary integrator (when you only + need to compute energies, for example). + + >>> context, context_integrator = context_cache.get_context(thermo_state) + """ def __init__(self, platform=None): self.platform = platform - def get_context(self, thermodynamic_state, integrator): - """Create a new context in the given thermodynamic state.""" + def get_context(self, thermodynamic_state, integrator=None): + """Create a new context in the given thermodynamic state. + + Parameters + ---------- + thermodynamic_state : states.ThermodynamicState + The thermodynamic state of the system. + integrator : simtk.openmm.Integrator, optional + The integrator to bind to the new context. If ``None``, an arbitrary + integrator is used. Currently, this is a ``LangevinIntegrator`` with + "V R O R V" splitting, but this might change in the future. Default + is ``None``. + + Returns + ------- + context : simtk.openmm.Context + The new context in the given thermodynamic system. + context_integrator : simtk.openmm.Integrator + The integrator bound to the context that can be used for + propagation. This is identical to the ``integrator`` argument + if it was passed. + + """ + if integrator is None: + integrator = integrators.LangevinIntegrator( + timestep=1.0*unit.femtoseconds, + splitting="V R O R V", + temperature=thermodynamic_state.temperature + ) context = thermodynamic_state.create_context(integrator, self.platform) return context, integrator diff --git a/openmmtools/integrators.py b/openmmtools/integrators.py index 01b6d9598..be419ecde 100644 --- a/openmmtools/integrators.py +++ b/openmmtools/integrators.py @@ -1081,7 +1081,7 @@ def __init__(self, Forces are only used in V-step. Handle multiple force groups by appending the force group index to V-steps, e.g. "V0" will only use forces from force group 0. "V" will perform a step using all forces. - "{" will cause metropolization, and must be followed later by a "}". + "{" will cause Metropolization, and must be followed later by a "}". temperature : np.unit.Quantity compatible with kelvin, default: 298.0*unit.kelvin @@ -1644,7 +1644,7 @@ def reset(self): Manually reset protocol work and other statistics. """ self.reset_protocol_work() - super(NonequilibriumLangevinIntegrator, self).reset() + super().reset() class AlchemicalNonequilibriumLangevinIntegrator(NonequilibriumLangevinIntegrator): """Allows nonequilibrium switching based on force parameters specified in alchemical_functions. @@ -1734,12 +1734,12 @@ def __init__(self, If not specified, no alchemical functions will be used. splitting : string, default: "O { V R H R V } O" - Sequence of R, V, O (and optionally V{i}), and { }substeps to be executed each timestep. There is also an H option, - which increments the global parameter `lambda` by 1/nsteps_neq for each step. + Sequence of "R", "V", "O" (and optionally "{", "}", "V0", "V1", ...) substeps to be executed each timestep. + "H" increments the global parameter `lambda` by 1/nsteps_neq for each step and accumulates protocol work. Forces are only used in V-step. Handle multiple force groups by appending the force group index to V-steps, e.g. "V0" will only use forces from force group 0. "V" will perform a step using all forces. - ( will cause metropolization, and must be followed later by a ). + { will cause Metropolization, and must be followed later by a }. temperature : np.unit.Quantity compatible with kelvin, default: 298.0*unit.kelvin Fictitious "bath" temperature @@ -1772,6 +1772,8 @@ def __init__(self, self._alchemical_functions = alchemical_functions self._n_steps_neq = nsteps_neq # number of integrator steps + if not hasattr(self, '_n_steps_per_cycle'): # for subclasses + self._n_steps_per_cycle = nsteps_neq # number of integrator steps per complete cycle # collect the system parameters. self._system_parameters = {system_parameter for system_parameter in alchemical_functions.keys()} @@ -1780,6 +1782,9 @@ def __init__(self, kwargs['splitting'] = splitting super(AlchemicalNonequilibriumLangevinIntegrator, self).__init__(*args, **kwargs) + if self._ORV_counts['H'] == 0: + raise ValueError('Integrator splitting string must contain at least one "H"') + @property def _step_dispatch_table(self): """dict: The dispatch table step_name -> add_step_function.""" @@ -1810,14 +1815,16 @@ def _add_global_variables(self): self.addGlobalVariable('Eold', 0) #old energy value before perturbation self.addGlobalVariable('Enew', 0) #new energy value after perturbation self.addGlobalVariable('lambda', 0.0) # parameter switched from 0 <--> 1 during course of integrating internal 'nsteps' of dynamics - self.addGlobalVariable('nsteps', self._n_steps_neq) # total number of NCMC steps to perform; this SHOULD NOT BE CHANGED during the protocol + self.addGlobalVariable('n_steps_neq', self._n_steps_neq) + self.addGlobalVariable('n_steps_per_cycle', self._n_steps_per_cycle) # total number of NCMC steps to perform; this SHOULD NOT BE CHANGED during the protocol + # TODO: Change 'step' to something that oesn't collide with the built-in lepton 'step()' function self.addGlobalVariable('step', 0) # step counter for handling initialization and terminating integration # Keep track of number of Hamiltonian updates per nonequilibrium switch n_H = self._ORV_counts['H'] # number of H updates per integrator step self._n_lambda_steps = self._n_steps_neq * n_H # number of Hamiltonian increments per switching step if self._n_steps_neq == 0: - self._n_lambda_steps = 1 # instantaneous switching + self._n_lambda_steps = n_H # instantaneous switching self.addGlobalVariable('n_lambda_steps', self._n_lambda_steps) # total number of NCMC steps to perform; this SHOULD NOT BE CHANGED during the protocol self.addGlobalVariable('lambda_step', 0) @@ -1833,7 +1840,10 @@ def _add_alchemical_perturbation_step(self): """ Add alchemical perturbation step, accumulating protocol work. - TODO: Extend this to be able to handle force groups? + .. todo :: + + This could be extended to only evaluate energies for force groups with global context parameters + to speed up work evaluations. """ # Store initial potential energy @@ -1866,14 +1876,14 @@ def _add_integrator_steps(self): if self._n_steps_neq == 0: # If nsteps = 0, we need to force execution on the first step only. self.beginIfBlock('step = 0') - super(AlchemicalNonequilibriumLangevinIntegrator, self)._add_integrator_steps() + super()._add_integrator_steps() self.addComputeGlobal("step", "step + 1") self.endBlock() else: #call the superclass function to insert the appropriate steps, provided the step number is less than n_steps self.beginIfBlock("step >= 0") - self.beginIfBlock("step < nsteps") - super(AlchemicalNonequilibriumLangevinIntegrator, self)._add_integrator_steps() + self.beginIfBlock("step < n_steps_per_cycle") + super()._add_integrator_steps() self.addComputeGlobal("step", "step + 1") self.endBlock() self.endBlock() @@ -1895,6 +1905,149 @@ def _add_alchemical_reset_step(self): # Add all dependent parameters self._add_update_alchemical_parameters_step() +class PeriodicNonequilibriumIntegrator(AlchemicalNonequilibriumLangevinIntegrator): + """ + Periodic nonequilibrium integrator where master alchemical parameter ``lambda`` + is driven through a periodic protocol: + + eq 0 for nsteps_eq | neq 0->1 over nsteps_neq | eq 1 for nsteps_eq | neq 1->0 for nsteps_neq + + Arbitrary Langevin splitting strings can be provided. + + .. warning :: This API is experimental, and subject to change. + + Examples + -------- + + Create a nonequilibrium integrator to switch the center of a harmonic oscillator between two locations, dwelling in either state to allow equilibration. + This example uses BAOAB (V R O R V) for integration. + + >>> # Create harmonic oscillator testsystem + >>> from openmmtools import testsystems + >>> from simtk import openmm, unit + >>> testsystem = testsystems.HarmonicOscillator() + >>> # Create a nonequilibrium alchemical integrator + >>> alchemical_functions = { 'testsystems_HarmonicOscillator_x0' : 'lambda' } + >>> nsteps_eq = 100 # number of steps to dwell in equilibrium at lambda = 0 or 1 + >>> nsteps_neq = 50 # number of steps in the switching trajectory where lambda is switched from 0 to 1 + >>> integrator = PeriodicAlchemicalNonequilibriumLangevinIntegrator( + ... temperature=300*unit.kelvin, collision_rate=1.0/unit.picoseconds, timestep=1.0*unit.femtoseconds, + ... alchemical_functions=alchemical_functions, splitting="V R H O R V", + ... nsteps_eq=nsteps_eq, nsteps_neq=nsteps_neq) + >>> # Create a Context + >>> context = openmm.Context(testsystem.system, integrator) + >>> # Run one periodic cycle: (eq 0) > (neq 0->1) > (eq 1) > (neq 1->0) + >>> context.setPositions(testsystem.positions) + >>> nsteps_per_period = 2*nsteps_eq + 2*nsteps_neq + >>> integrator.step(nsteps_per_period) + >>> protocol_work = integrator.protocol_work # retrieve protocol work (excludes shadow work) + >>> total_work = integrator.total_work # retrieve total work (includes shadow work, if requested) + >>> # Run another cycle + >>> integrator.step(nsteps_per_period) + >>> # Reset and run again + >>> context.setPositions(testsystem.positions) + >>> integrator.reset() + >>> integrator.step(nsteps_per_period) + """ + def __init__(self, + alchemical_functions=None, + nsteps_eq=1000, + nsteps_neq=100, + splitting="V R H O R V", + **kwargs): + """ + Parameters + ---------- + nsteps_eq : int, optional, default=1000 + Number of equilibration steps to dwell within lambda = 0 or 1 when reached + nsteps_neq : int, optional, default=100 + Number of nonequilibrium switching steps for 0->1 and 1->0 switches + splitting : string, default: "V R H O R V" + Sequence of "R", "V", "O" (and optionally "{", "}", "V0", "V1", ...) substeps to be executed each timestep. + "H" increments the global parameter `lambda` by 1/nsteps_neq for each step and accumulates protocol work. + + Forces are only used in V-step. Handle multiple force groups by appending the force group index + to V-steps, e.g. "V0" will only use forces from force group 0. "V" will perform a step using all forces. + { will cause Metropolization, and must be followed later by a }. + """ + # Check that a valid set of steps has been specified + n_steps_per_cycle = 2*nsteps_eq + 2*nsteps_neq + if n_steps_per_cycle <= 0: + raise ValueError(f'nsteps_per_period = {n_steps_per_cycle} must be > 0') + + self._n_steps_eq = nsteps_eq # store number of equilibration steps to dwell within lambda = 0 or 1 when reached + self._n_steps_per_cycle = n_steps_per_cycle + super().__init__(alchemical_functions, splitting, nsteps_neq=nsteps_neq, **kwargs) + + def _add_global_variables(self): + """ + modify the super (_add_global_variables) to add a collector for forward and reverse annealing, as well as to specify the number of equilibration + steps at endstates. + """ + super()._add_global_variables() + self.addGlobalVariable('n_steps_eq', self._n_steps_eq) # number of steps per nonequilibrium switching phase (forward or backward) + + def _add_integrator_steps(self): + """ + Override the base class to insert reset steps around the integrator. + """ + # First step: Constrain positions and velocities and reset work accumulators and alchemical integrators + self.beginIfBlock('step = 0') + self.addConstrainPositions() + self.addConstrainVelocities() + self._add_reset_protocol_work_step() + self._add_alchemical_reset_step() # set alchemical parameters too + self.endBlock() + + # Main body + self.beginIfBlock("step >= 0") + NonequilibriumLangevinIntegrator._add_integrator_steps(self) # includes H step which updates alchemical state and accumulates work + self.addComputeGlobal("step", "step + 1") + self.endBlock() + + # We allow this integrator to cycle instead of halting at the final step + self.beginIfBlock("step >= n_steps_per_cycle") + self.addComputeGlobal("step", "0") + self.addComputeGlobal("lambda_step", "0") + self.endBlock() + + # Reset step + self.beginIfBlock('step = -1') + self._add_reset_protocol_work_step() + self._add_alchemical_reset_step() # sets step to 0 + self.endBlock() + + def _add_alchemical_perturbation_step(self): + """ + Add alchemical perturbation step, accumulating protocol work. + + .. todo :: + + This could be extended to only evaluate energies for force groups with global context parameters + to speed up work evaluations. + + """ + # Store initial potential energy + self.addComputeGlobal("Eold", "energy") + + # Compute lambda increment (only nonzero in forward or backward switching phases) + is_forward_switch = "step((step+0.5)-n_steps_eq)*step((n_steps_eq+n_steps_neq) - (step+0.5))" #logic: define bool forward switch + is_backward_switch = "step((step+0.5)-(n_steps_eq+n_steps_neq+n_steps_eq))*step(n_steps_per_cycle - (step+0.5))" #logic: define bool backward switch + lambda_increment_expression = f"lambda + delta_lambda*is_forward_switch - delta_lambda*is_backward_switch;" + lambda_increment_expression += f"is_forward_switch = {is_forward_switch};" + lambda_increment_expression += f"is_backward_switch = {is_backward_switch};" + lambda_increment_expression += "delta_lambda = 1/n_lambda_steps;" + + self.addComputeGlobal('lambda', lambda_increment_expression) # increment lambda + self.addComputeGlobal('lambda_step', 'lambda_step + 1') + + # Update all slaved alchemical parameters + self._add_update_alchemical_parameters_step() + + # Accumulate protocol work + self.addComputeGlobal("Enew", "energy") + self.addComputeGlobal("protocol_work", "protocol_work + (Enew-Eold)") + class ExternalPerturbationLangevinIntegrator(NonequilibriumLangevinIntegrator): """ Create a LangevinSplittingIntegrator that accounts for external perturbations and tracks protocol work. @@ -2125,22 +2278,29 @@ def __init__(self, *args, **kwargs): kwargs['splitting'] = "O { V R V } O" super(GHMCIntegrator, self).__init__(*args, **kwargs) + class FIREMinimizationIntegrator(mm.CustomIntegrator): """Fast Internal Relaxation Engine (FIRE) minimization. + Notes ----- This integrator is taken verbatim from Peter Eastman's example appearing in the CustomIntegrator header file documentation. + References ---------- Erik Bitzek, Pekka Koskinen, Franz Gaehler, Michael Moseler, and Peter Gumbsch. Structural Relaxation Made Simple. PRL 97:170201, 2006. http://dx.doi.org/10.1103/PhysRevLett.97.170201 + Examples -------- >>> from openmmtools import testsystems >>> from simtk import openmm >>> t = testsystems.AlanineDipeptideVacuum() >>> system, positions = t.system, t.positions + + Create a FIRE integrator with default parameters and minimize for 100 steps + >>> integrator = FIREMinimizationIntegrator() >>> context = openmm.Context(system, integrator) >>> context.setPositions(positions) diff --git a/openmmtools/mcmc.py b/openmmtools/mcmc.py index 1d73335c0..6f555c084 100644 --- a/openmmtools/mcmc.py +++ b/openmmtools/mcmc.py @@ -570,7 +570,7 @@ class BaseIntegratorMove(MCMCMove): reassign_velocities : bool, optional If True, the velocities will be reassigned from the Maxwell-Boltzmann distribution at the beginning of the move (default is False). - restart_attempts : int, optional + n_restart_attempts : int, optional When greater than 0, if after the integration there are NaNs in energies, the move will restart. When the integrator has a random component, this may help recovering. On the last attempt, the ``Context`` is @@ -583,7 +583,7 @@ class BaseIntegratorMove(MCMCMove): n_steps : int context_cache : openmmtools.cache.ContextCache reassign_velocities : bool - restart_attempts : int or None + n_restart_attempts : int or None Examples -------- diff --git a/openmmtools/multistate/mixing/_mix_replicas.c b/openmmtools/multistate/mixing/_mix_replicas.c index f4edbde40..29df1ad68 100644 --- a/openmmtools/multistate/mixing/_mix_replicas.c +++ b/openmmtools/multistate/mixing/_mix_replicas.c @@ -1,4 +1,4 @@ -/* Generated by Cython 0.29.4 */ +/* Generated by Cython 0.29.16 */ /* BEGIN: Cython Metadata { @@ -20,8 +20,8 @@ END: Cython Metadata */ #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_4" -#define CYTHON_HEX_VERSION 0x001D04F0 +#define CYTHON_ABI "0_29_16" +#define CYTHON_HEX_VERSION 0x001D10F0 #define CYTHON_FUTURE_DIVISION 0 #include #ifndef offsetof @@ -323,8 +323,13 @@ END: Cython Metadata */ #define __Pyx_DefaultClassType PyClass_Type #else #define __Pyx_BUILTIN_MODULE_NAME "builtins" +#if PY_VERSION_HEX >= 0x030800A4 && PY_VERSION_HEX < 0x030800B2 + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a, 0, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) +#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 @@ -359,26 +364,6 @@ END: Cython Metadata */ #else #define __Pyx_PyFastCFunction_Check(func) 0 #endif -#if CYTHON_USE_DICT_VERSIONS -#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);\ - }\ - } -#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 #if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) #define PyObject_Malloc(s) PyMem_Malloc(s) #define PyObject_Free(p) PyMem_Free(p) @@ -512,8 +497,10 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #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) @@ -640,7 +627,8 @@ typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* enc 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_DEFAULT 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 @@ -1014,7 +1002,7 @@ struct __pyx_memoryview_obj { }; -/* "View.MemoryView":961 +/* "View.MemoryView":965 * * @cname('__pyx_memoryviewslice') * cdef class _memoryviewslice(memoryview): # <<<<<<<<<<<<<< @@ -1065,7 +1053,7 @@ struct __pyx_vtabstruct_memoryview { static struct __pyx_vtabstruct_memoryview *__pyx_vtabptr_memoryview; -/* "View.MemoryView":961 +/* "View.MemoryView":965 * * @cname('__pyx_memoryviewslice') * cdef class _memoryviewslice(memoryview): # <<<<<<<<<<<<<< @@ -1257,7 +1245,7 @@ static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObje #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, int nargs, PyObject *kwargs); +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 @@ -1374,6 +1362,32 @@ static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tsta /* GetAttr3.proto */ static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *); +/* 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) {\ @@ -1514,11 +1528,6 @@ static CYTHON_INLINE int __Pyx_PyList_Append(PyObject* list, PyObject* x) { /* None.proto */ static CYTHON_INLINE long __Pyx_div_long(long, long); -/* WriteUnraisableException.proto */ -static void __Pyx_WriteUnraisable(const char *name, int clineno, - int lineno, const char *filename, - int full_traceback, int nogil); - /* ImportFrom.proto */ static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name); @@ -5201,7 +5210,7 @@ static void __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_2__deal * 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); @@ -5211,8 +5220,8 @@ static void __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_2__deal * def __dealloc__(memoryview self): * if self.obj is not None: * __Pyx_ReleaseBuffer(&self.view) # <<<<<<<<<<<<<< + * elif (<__pyx_buffer *> &self.view).obj == Py_None: * - * cdef int i */ __Pyx_ReleaseBuffer((&__pyx_v_self->view)); @@ -5221,11 +5230,50 @@ static void __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_2__deal * 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":375 + * 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":377 + * 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":378 + * + * (<__pyx_buffer *> &self.view).obj = NULL + * Py_DECREF(Py_None) # <<<<<<<<<<<<<< + * + * cdef int i + */ + Py_DECREF(Py_None); + + /* "View.MemoryView":375 + * 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":378 + /* "View.MemoryView":382 * cdef int i * global __pyx_memoryview_thread_locks_used * if self.lock != NULL: # <<<<<<<<<<<<<< @@ -5235,7 +5283,7 @@ static void __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_2__deal __pyx_t_2 = ((__pyx_v_self->lock != NULL) != 0); if (__pyx_t_2) { - /* "View.MemoryView":379 + /* "View.MemoryView":383 * global __pyx_memoryview_thread_locks_used * if self.lock != NULL: * for i in range(__pyx_memoryview_thread_locks_used): # <<<<<<<<<<<<<< @@ -5247,7 +5295,7 @@ static void __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_2__deal for (__pyx_t_5 = 0; __pyx_t_5 < __pyx_t_4; __pyx_t_5+=1) { __pyx_v_i = __pyx_t_5; - /* "View.MemoryView":380 + /* "View.MemoryView":384 * if self.lock != NULL: * for i in range(__pyx_memoryview_thread_locks_used): * if __pyx_memoryview_thread_locks[i] is self.lock: # <<<<<<<<<<<<<< @@ -5257,7 +5305,7 @@ static void __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_2__deal __pyx_t_2 = (((__pyx_memoryview_thread_locks[__pyx_v_i]) == __pyx_v_self->lock) != 0); if (__pyx_t_2) { - /* "View.MemoryView":381 + /* "View.MemoryView":385 * for i in range(__pyx_memoryview_thread_locks_used): * if __pyx_memoryview_thread_locks[i] is self.lock: * __pyx_memoryview_thread_locks_used -= 1 # <<<<<<<<<<<<<< @@ -5266,7 +5314,7 @@ static void __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_2__deal */ __pyx_memoryview_thread_locks_used = (__pyx_memoryview_thread_locks_used - 1); - /* "View.MemoryView":382 + /* "View.MemoryView":386 * if __pyx_memoryview_thread_locks[i] is self.lock: * __pyx_memoryview_thread_locks_used -= 1 * if i != __pyx_memoryview_thread_locks_used: # <<<<<<<<<<<<<< @@ -5276,7 +5324,7 @@ static void __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_2__deal __pyx_t_2 = ((__pyx_v_i != __pyx_memoryview_thread_locks_used) != 0); if (__pyx_t_2) { - /* "View.MemoryView":384 + /* "View.MemoryView":388 * 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]) # <<<<<<<<<<<<<< @@ -5286,7 +5334,7 @@ static void __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_2__deal __pyx_t_6 = (__pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used]); __pyx_t_7 = (__pyx_memoryview_thread_locks[__pyx_v_i]); - /* "View.MemoryView":383 + /* "View.MemoryView":387 * __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] = ( # <<<<<<<<<<<<<< @@ -5296,7 +5344,7 @@ static void __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_2__deal (__pyx_memoryview_thread_locks[__pyx_v_i]) = __pyx_t_6; (__pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used]) = __pyx_t_7; - /* "View.MemoryView":382 + /* "View.MemoryView":386 * if __pyx_memoryview_thread_locks[i] is self.lock: * __pyx_memoryview_thread_locks_used -= 1 * if i != __pyx_memoryview_thread_locks_used: # <<<<<<<<<<<<<< @@ -5305,7 +5353,7 @@ static void __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_2__deal */ } - /* "View.MemoryView":385 + /* "View.MemoryView":389 * __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 # <<<<<<<<<<<<<< @@ -5314,7 +5362,7 @@ static void __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_2__deal */ goto __pyx_L6_break; - /* "View.MemoryView":380 + /* "View.MemoryView":384 * if self.lock != NULL: * for i in range(__pyx_memoryview_thread_locks_used): * if __pyx_memoryview_thread_locks[i] is self.lock: # <<<<<<<<<<<<<< @@ -5325,7 +5373,7 @@ static void __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_2__deal } /*else*/ { - /* "View.MemoryView":387 + /* "View.MemoryView":391 * break * else: * PyThread_free_lock(self.lock) # <<<<<<<<<<<<<< @@ -5336,7 +5384,7 @@ static void __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_2__deal } __pyx_L6_break:; - /* "View.MemoryView":378 + /* "View.MemoryView":382 * cdef int i * global __pyx_memoryview_thread_locks_used * if self.lock != NULL: # <<<<<<<<<<<<<< @@ -5357,7 +5405,7 @@ static void __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_2__deal __Pyx_RefNannyFinishContext(); } -/* "View.MemoryView":389 +/* "View.MemoryView":393 * PyThread_free_lock(self.lock) * * cdef char *get_item_pointer(memoryview self, object index) except NULL: # <<<<<<<<<<<<<< @@ -5380,7 +5428,7 @@ static char *__pyx_memoryview_get_item_pointer(struct __pyx_memoryview_obj *__py char *__pyx_t_7; __Pyx_RefNannySetupContext("get_item_pointer", 0); - /* "View.MemoryView":391 + /* "View.MemoryView":395 * cdef char *get_item_pointer(memoryview self, object index) except NULL: * cdef Py_ssize_t dim * cdef char *itemp = self.view.buf # <<<<<<<<<<<<<< @@ -5389,7 +5437,7 @@ static char *__pyx_memoryview_get_item_pointer(struct __pyx_memoryview_obj *__py */ __pyx_v_itemp = ((char *)__pyx_v_self->view.buf); - /* "View.MemoryView":393 + /* "View.MemoryView":397 * cdef char *itemp = self.view.buf * * for dim, idx in enumerate(index): # <<<<<<<<<<<<<< @@ -5401,26 +5449,26 @@ static char *__pyx_memoryview_get_item_pointer(struct __pyx_memoryview_obj *__py __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(1, 393, __pyx_L1_error) + __pyx_t_3 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_v_index); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 397, __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(1, 393, __pyx_L1_error) + __pyx_t_4 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 397, __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(1, 393, __pyx_L1_error) + __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(1, 397, __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(1, 393, __pyx_L1_error) + __pyx_t_5 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 397, __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(1, 393, __pyx_L1_error) + __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(1, 397, __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(1, 393, __pyx_L1_error) + __pyx_t_5 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 397, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_5); #endif } @@ -5430,7 +5478,7 @@ static char *__pyx_memoryview_get_item_pointer(struct __pyx_memoryview_obj *__py PyObject* exc_type = PyErr_Occurred(); if (exc_type) { if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear(); - else __PYX_ERR(1, 393, __pyx_L1_error) + else __PYX_ERR(1, 397, __pyx_L1_error) } break; } @@ -5441,18 +5489,18 @@ static char *__pyx_memoryview_get_item_pointer(struct __pyx_memoryview_obj *__py __pyx_v_dim = __pyx_t_1; __pyx_t_1 = (__pyx_t_1 + 1); - /* "View.MemoryView":394 + /* "View.MemoryView":398 * * 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(1, 394, __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(1, 394, __pyx_L1_error) + __pyx_t_6 = __Pyx_PyIndex_AsSsize_t(__pyx_v_idx); if (unlikely((__pyx_t_6 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(1, 398, __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(1, 398, __pyx_L1_error) __pyx_v_itemp = __pyx_t_7; - /* "View.MemoryView":393 + /* "View.MemoryView":397 * cdef char *itemp = self.view.buf * * for dim, idx in enumerate(index): # <<<<<<<<<<<<<< @@ -5462,7 +5510,7 @@ static char *__pyx_memoryview_get_item_pointer(struct __pyx_memoryview_obj *__py } __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - /* "View.MemoryView":396 + /* "View.MemoryView":400 * itemp = pybuffer_index(&self.view, itemp, idx, dim) * * return itemp # <<<<<<<<<<<<<< @@ -5472,7 +5520,7 @@ static char *__pyx_memoryview_get_item_pointer(struct __pyx_memoryview_obj *__py __pyx_r = __pyx_v_itemp; goto __pyx_L0; - /* "View.MemoryView":389 + /* "View.MemoryView":393 * PyThread_free_lock(self.lock) * * cdef char *get_item_pointer(memoryview self, object index) except NULL: # <<<<<<<<<<<<<< @@ -5492,7 +5540,7 @@ static char *__pyx_memoryview_get_item_pointer(struct __pyx_memoryview_obj *__py return __pyx_r; } -/* "View.MemoryView":399 +/* "View.MemoryView":403 * * * def __getitem__(memoryview self, object index): # <<<<<<<<<<<<<< @@ -5527,7 +5575,7 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_4_ char *__pyx_t_6; __Pyx_RefNannySetupContext("__getitem__", 0); - /* "View.MemoryView":400 + /* "View.MemoryView":404 * * def __getitem__(memoryview self, object index): * if index is Ellipsis: # <<<<<<<<<<<<<< @@ -5538,7 +5586,7 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_4_ __pyx_t_2 = (__pyx_t_1 != 0); if (__pyx_t_2) { - /* "View.MemoryView":401 + /* "View.MemoryView":405 * def __getitem__(memoryview self, object index): * if index is Ellipsis: * return self # <<<<<<<<<<<<<< @@ -5550,7 +5598,7 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_4_ __pyx_r = ((PyObject *)__pyx_v_self); goto __pyx_L0; - /* "View.MemoryView":400 + /* "View.MemoryView":404 * * def __getitem__(memoryview self, object index): * if index is Ellipsis: # <<<<<<<<<<<<<< @@ -5559,14 +5607,14 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_4_ */ } - /* "View.MemoryView":403 + /* "View.MemoryView":407 * 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(1, 403, __pyx_L1_error) + __pyx_t_3 = _unellipsify(__pyx_v_index, __pyx_v_self->view.ndim); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 407, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); if (likely(__pyx_t_3 != Py_None)) { PyObject* sequence = __pyx_t_3; @@ -5574,7 +5622,7 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_4_ if (unlikely(size != 2)) { if (size > 2) __Pyx_RaiseTooManyValuesError(2); else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(1, 403, __pyx_L1_error) + __PYX_ERR(1, 407, __pyx_L1_error) } #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS __pyx_t_4 = PyTuple_GET_ITEM(sequence, 0); @@ -5582,31 +5630,31 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_4_ __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(1, 403, __pyx_L1_error) + __pyx_t_4 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 407, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); - __pyx_t_5 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 403, __pyx_L1_error) + __pyx_t_5 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 407, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_5); #endif __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; } else { - __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(1, 403, __pyx_L1_error) + __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(1, 407, __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":406 + /* "View.MemoryView":410 * * 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(1, 406, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_have_slices); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(1, 410, __pyx_L1_error) if (__pyx_t_2) { - /* "View.MemoryView":407 + /* "View.MemoryView":411 * cdef char *itemp * if have_slices: * return memview_slice(self, indices) # <<<<<<<<<<<<<< @@ -5614,13 +5662,13 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_4_ * 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(1, 407, __pyx_L1_error) + __pyx_t_3 = ((PyObject *)__pyx_memview_slice(__pyx_v_self, __pyx_v_indices)); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 411, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_r = __pyx_t_3; __pyx_t_3 = 0; goto __pyx_L0; - /* "View.MemoryView":406 + /* "View.MemoryView":410 * * cdef char *itemp * if have_slices: # <<<<<<<<<<<<<< @@ -5629,7 +5677,7 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_4_ */ } - /* "View.MemoryView":409 + /* "View.MemoryView":413 * return memview_slice(self, indices) * else: * itemp = self.get_item_pointer(indices) # <<<<<<<<<<<<<< @@ -5637,10 +5685,10 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_4_ * */ /*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(1, 409, __pyx_L1_error) + __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(1, 413, __pyx_L1_error) __pyx_v_itemp = __pyx_t_6; - /* "View.MemoryView":410 + /* "View.MemoryView":414 * else: * itemp = self.get_item_pointer(indices) * return self.convert_item_to_object(itemp) # <<<<<<<<<<<<<< @@ -5648,14 +5696,14 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_4_ * 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(1, 410, __pyx_L1_error) + __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(1, 414, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_r = __pyx_t_3; __pyx_t_3 = 0; goto __pyx_L0; } - /* "View.MemoryView":399 + /* "View.MemoryView":403 * * * def __getitem__(memoryview self, object index): # <<<<<<<<<<<<<< @@ -5678,7 +5726,7 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_4_ return __pyx_r; } -/* "View.MemoryView":412 +/* "View.MemoryView":416 * return self.convert_item_to_object(itemp) * * def __setitem__(memoryview self, object index, object value): # <<<<<<<<<<<<<< @@ -5711,7 +5759,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_6__setit __Pyx_RefNannySetupContext("__setitem__", 0); __Pyx_INCREF(__pyx_v_index); - /* "View.MemoryView":413 + /* "View.MemoryView":417 * * def __setitem__(memoryview self, object index, object value): * if self.view.readonly: # <<<<<<<<<<<<<< @@ -5721,20 +5769,20 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_6__setit __pyx_t_1 = (__pyx_v_self->view.readonly != 0); if (unlikely(__pyx_t_1)) { - /* "View.MemoryView":414 + /* "View.MemoryView":418 * 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__8, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 414, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__8, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 418, __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(1, 414, __pyx_L1_error) + __PYX_ERR(1, 418, __pyx_L1_error) - /* "View.MemoryView":413 + /* "View.MemoryView":417 * * def __setitem__(memoryview self, object index, object value): * if self.view.readonly: # <<<<<<<<<<<<<< @@ -5743,14 +5791,14 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_6__setit */ } - /* "View.MemoryView":416 + /* "View.MemoryView":420 * 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(1, 416, __pyx_L1_error) + __pyx_t_2 = _unellipsify(__pyx_v_index, __pyx_v_self->view.ndim); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 420, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); if (likely(__pyx_t_2 != Py_None)) { PyObject* sequence = __pyx_t_2; @@ -5758,7 +5806,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_6__setit if (unlikely(size != 2)) { if (size > 2) __Pyx_RaiseTooManyValuesError(2); else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(1, 416, __pyx_L1_error) + __PYX_ERR(1, 420, __pyx_L1_error) } #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); @@ -5766,67 +5814,67 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_6__setit __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(1, 416, __pyx_L1_error) + __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 420, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); - __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 416, __pyx_L1_error) + __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 420, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); #endif __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; } else { - __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(1, 416, __pyx_L1_error) + __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(1, 420, __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":418 + /* "View.MemoryView":422 * 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(1, 418, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_have_slices); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(1, 422, __pyx_L1_error) if (__pyx_t_1) { - /* "View.MemoryView":419 + /* "View.MemoryView":423 * * 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(1, 419, __pyx_L1_error) + __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(1, 423, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __pyx_v_obj = __pyx_t_2; __pyx_t_2 = 0; - /* "View.MemoryView":420 + /* "View.MemoryView":424 * 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(1, 420, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_obj); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(1, 424, __pyx_L1_error) if (__pyx_t_1) { - /* "View.MemoryView":421 + /* "View.MemoryView":425 * 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(1, 421, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_GetItem(((PyObject *)__pyx_v_self), __pyx_v_index); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 425, __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(1, 421, __pyx_L1_error) + __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(1, 425, __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":420 + /* "View.MemoryView":424 * if have_slices: * obj = self.is_slice(value) * if obj: # <<<<<<<<<<<<<< @@ -5836,7 +5884,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_6__setit goto __pyx_L5; } - /* "View.MemoryView":423 + /* "View.MemoryView":427 * self.setitem_slice_assignment(self[index], obj) * else: * self.setitem_slice_assign_scalar(self[index], value) # <<<<<<<<<<<<<< @@ -5844,17 +5892,17 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_6__setit * 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(1, 423, __pyx_L1_error) + __pyx_t_4 = __Pyx_PyObject_GetItem(((PyObject *)__pyx_v_self), __pyx_v_index); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 427, __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(1, 423, __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(1, 423, __pyx_L1_error) + if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_memoryview_type))))) __PYX_ERR(1, 427, __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(1, 427, __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":418 + /* "View.MemoryView":422 * have_slices, index = _unellipsify(index, self.view.ndim) * * if have_slices: # <<<<<<<<<<<<<< @@ -5864,7 +5912,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_6__setit goto __pyx_L4; } - /* "View.MemoryView":425 + /* "View.MemoryView":429 * self.setitem_slice_assign_scalar(self[index], value) * else: * self.setitem_indexed(index, value) # <<<<<<<<<<<<<< @@ -5872,13 +5920,13 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_6__setit * 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(1, 425, __pyx_L1_error) + __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(1, 429, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; } __pyx_L4:; - /* "View.MemoryView":412 + /* "View.MemoryView":416 * return self.convert_item_to_object(itemp) * * def __setitem__(memoryview self, object index, object value): # <<<<<<<<<<<<<< @@ -5903,7 +5951,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_6__setit return __pyx_r; } -/* "View.MemoryView":427 +/* "View.MemoryView":431 * self.setitem_indexed(index, value) * * cdef is_slice(self, obj): # <<<<<<<<<<<<<< @@ -5926,7 +5974,7 @@ static PyObject *__pyx_memoryview_is_slice(struct __pyx_memoryview_obj *__pyx_v_ __Pyx_RefNannySetupContext("is_slice", 0); __Pyx_INCREF(__pyx_v_obj); - /* "View.MemoryView":428 + /* "View.MemoryView":432 * * cdef is_slice(self, obj): * if not isinstance(obj, memoryview): # <<<<<<<<<<<<<< @@ -5937,7 +5985,7 @@ static PyObject *__pyx_memoryview_is_slice(struct __pyx_memoryview_obj *__pyx_v_ __pyx_t_2 = ((!(__pyx_t_1 != 0)) != 0); if (__pyx_t_2) { - /* "View.MemoryView":429 + /* "View.MemoryView":433 * cdef is_slice(self, obj): * if not isinstance(obj, memoryview): * try: # <<<<<<<<<<<<<< @@ -5953,34 +6001,34 @@ static PyObject *__pyx_memoryview_is_slice(struct __pyx_memoryview_obj *__pyx_v_ __Pyx_XGOTREF(__pyx_t_5); /*try:*/ { - /* "View.MemoryView":430 + /* "View.MemoryView":434 * 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(1, 430, __pyx_L4_error) + __pyx_t_6 = __Pyx_PyInt_From_int(((__pyx_v_self->flags & (~PyBUF_WRITABLE)) | PyBUF_ANY_CONTIGUOUS)); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 434, __pyx_L4_error) __Pyx_GOTREF(__pyx_t_6); - /* "View.MemoryView":431 + /* "View.MemoryView":435 * 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(1, 431, __pyx_L4_error) + __pyx_t_7 = __Pyx_PyBool_FromLong(__pyx_v_self->dtype_is_object); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 435, __pyx_L4_error) __Pyx_GOTREF(__pyx_t_7); - /* "View.MemoryView":430 + /* "View.MemoryView":434 * 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(1, 430, __pyx_L4_error) + __pyx_t_8 = PyTuple_New(3); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 434, __pyx_L4_error) __Pyx_GOTREF(__pyx_t_8); __Pyx_INCREF(__pyx_v_obj); __Pyx_GIVEREF(__pyx_v_obj); @@ -5991,13 +6039,13 @@ static PyObject *__pyx_memoryview_is_slice(struct __pyx_memoryview_obj *__pyx_v_ 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(1, 430, __pyx_L4_error) + __pyx_t_7 = __Pyx_PyObject_Call(((PyObject *)__pyx_memoryview_type), __pyx_t_8, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 434, __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":429 + /* "View.MemoryView":433 * cdef is_slice(self, obj): * if not isinstance(obj, memoryview): * try: # <<<<<<<<<<<<<< @@ -6014,7 +6062,7 @@ static PyObject *__pyx_memoryview_is_slice(struct __pyx_memoryview_obj *__pyx_v_ __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; - /* "View.MemoryView":432 + /* "View.MemoryView":436 * obj = memoryview(obj, self.flags & ~PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS, * self.dtype_is_object) * except TypeError: # <<<<<<<<<<<<<< @@ -6024,12 +6072,12 @@ static PyObject *__pyx_memoryview_is_slice(struct __pyx_memoryview_obj *__pyx_v_ __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(1, 432, __pyx_L6_except_error) + if (__Pyx_GetException(&__pyx_t_7, &__pyx_t_8, &__pyx_t_6) < 0) __PYX_ERR(1, 436, __pyx_L6_except_error) __Pyx_GOTREF(__pyx_t_7); __Pyx_GOTREF(__pyx_t_8); __Pyx_GOTREF(__pyx_t_6); - /* "View.MemoryView":433 + /* "View.MemoryView":437 * self.dtype_is_object) * except TypeError: * return None # <<<<<<<<<<<<<< @@ -6046,7 +6094,7 @@ static PyObject *__pyx_memoryview_is_slice(struct __pyx_memoryview_obj *__pyx_v_ goto __pyx_L6_except_error; __pyx_L6_except_error:; - /* "View.MemoryView":429 + /* "View.MemoryView":433 * cdef is_slice(self, obj): * if not isinstance(obj, memoryview): * try: # <<<<<<<<<<<<<< @@ -6067,7 +6115,7 @@ static PyObject *__pyx_memoryview_is_slice(struct __pyx_memoryview_obj *__pyx_v_ __pyx_L9_try_end:; } - /* "View.MemoryView":428 + /* "View.MemoryView":432 * * cdef is_slice(self, obj): * if not isinstance(obj, memoryview): # <<<<<<<<<<<<<< @@ -6076,7 +6124,7 @@ static PyObject *__pyx_memoryview_is_slice(struct __pyx_memoryview_obj *__pyx_v_ */ } - /* "View.MemoryView":435 + /* "View.MemoryView":439 * return None * * return obj # <<<<<<<<<<<<<< @@ -6088,7 +6136,7 @@ static PyObject *__pyx_memoryview_is_slice(struct __pyx_memoryview_obj *__pyx_v_ __pyx_r = __pyx_v_obj; goto __pyx_L0; - /* "View.MemoryView":427 + /* "View.MemoryView":431 * self.setitem_indexed(index, value) * * cdef is_slice(self, obj): # <<<<<<<<<<<<<< @@ -6110,7 +6158,7 @@ static PyObject *__pyx_memoryview_is_slice(struct __pyx_memoryview_obj *__pyx_v_ return __pyx_r; } -/* "View.MemoryView":437 +/* "View.MemoryView":441 * return obj * * cdef setitem_slice_assignment(self, dst, src): # <<<<<<<<<<<<<< @@ -6123,56 +6171,60 @@ static PyObject *__pyx_memoryview_setitem_slice_assignment(struct __pyx_memoryvi __Pyx_memviewslice __pyx_v_src_slice; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; - int __pyx_t_3; + __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; __Pyx_RefNannySetupContext("setitem_slice_assignment", 0); - /* "View.MemoryView":441 + /* "View.MemoryView":445 * 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(1, 441, __pyx_L1_error) + if (!(likely(((__pyx_v_src) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_src, __pyx_memoryview_type))))) __PYX_ERR(1, 445, __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(1, 445, __pyx_L1_error) - /* "View.MemoryView":442 + /* "View.MemoryView":446 * * 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(1, 442, __pyx_L1_error) + if (!(likely(((__pyx_v_dst) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_dst, __pyx_memoryview_type))))) __PYX_ERR(1, 446, __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(1, 446, __pyx_L1_error) - /* "View.MemoryView":443 + /* "View.MemoryView":447 * 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_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_src, __pyx_n_s_ndim); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 443, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 443, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_dst, __pyx_n_s_ndim); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 443, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 443, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_src, __pyx_n_s_ndim); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 447, __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(1, 447, __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(1, 447, __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(1, 447, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - /* "View.MemoryView":441 + /* "View.MemoryView":445 * 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_4 = __pyx_memoryview_copy_contents((__pyx_memoryview_get_slice_from_memoryview(((struct __pyx_memoryview_obj *)__pyx_v_src), (&__pyx_v_src_slice))[0]), (__pyx_memoryview_get_slice_from_memoryview(((struct __pyx_memoryview_obj *)__pyx_v_dst), (&__pyx_v_dst_slice))[0]), __pyx_t_2, __pyx_t_3, __pyx_v_self->dtype_is_object); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 441, __pyx_L1_error) + __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(1, 445, __pyx_L1_error) - /* "View.MemoryView":437 + /* "View.MemoryView":441 * return obj * * cdef setitem_slice_assignment(self, dst, src): # <<<<<<<<<<<<<< @@ -6184,7 +6236,7 @@ static PyObject *__pyx_memoryview_setitem_slice_assignment(struct __pyx_memoryvi __pyx_r = Py_None; __Pyx_INCREF(Py_None); goto __pyx_L0; __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_3); __Pyx_AddTraceback("View.MemoryView.memoryview.setitem_slice_assignment", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; @@ -6193,7 +6245,7 @@ static PyObject *__pyx_memoryview_setitem_slice_assignment(struct __pyx_memoryvi return __pyx_r; } -/* "View.MemoryView":445 +/* "View.MemoryView":449 * src.ndim, dst.ndim, self.dtype_is_object) * * cdef setitem_slice_assign_scalar(self, memoryview dst, value): # <<<<<<<<<<<<<< @@ -6209,20 +6261,21 @@ static PyObject *__pyx_memoryview_setitem_slice_assign_scalar(struct __pyx_memor __Pyx_memviewslice __pyx_v_tmp_slice; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations - int __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - int __pyx_t_3; + __Pyx_memviewslice *__pyx_t_1; + int __pyx_t_2; + PyObject *__pyx_t_3 = NULL; int __pyx_t_4; - char const *__pyx_t_5; - PyObject *__pyx_t_6 = NULL; + 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; __Pyx_RefNannySetupContext("setitem_slice_assign_scalar", 0); - /* "View.MemoryView":447 + /* "View.MemoryView":451 * cdef setitem_slice_assign_scalar(self, memoryview dst, value): * cdef int array[128] * cdef void *tmp = NULL # <<<<<<<<<<<<<< @@ -6231,26 +6284,27 @@ static PyObject *__pyx_memoryview_setitem_slice_assign_scalar(struct __pyx_memor */ __pyx_v_tmp = NULL; - /* "View.MemoryView":452 + /* "View.MemoryView":456 * 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_v_dst_slice = __pyx_memoryview_get_slice_from_memoryview(__pyx_v_dst, (&__pyx_v_tmp_slice)); + __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(1, 456, __pyx_L1_error) + __pyx_v_dst_slice = __pyx_t_1; - /* "View.MemoryView":454 + /* "View.MemoryView":458 * 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_1 = ((((size_t)__pyx_v_self->view.itemsize) > (sizeof(__pyx_v_array))) != 0); - if (__pyx_t_1) { + __pyx_t_2 = ((((size_t)__pyx_v_self->view.itemsize) > (sizeof(__pyx_v_array))) != 0); + if (__pyx_t_2) { - /* "View.MemoryView":455 + /* "View.MemoryView":459 * * if self.view.itemsize > sizeof(array): * tmp = PyMem_Malloc(self.view.itemsize) # <<<<<<<<<<<<<< @@ -6259,26 +6313,26 @@ static PyObject *__pyx_memoryview_setitem_slice_assign_scalar(struct __pyx_memor */ __pyx_v_tmp = PyMem_Malloc(__pyx_v_self->view.itemsize); - /* "View.MemoryView":456 + /* "View.MemoryView":460 * if self.view.itemsize > sizeof(array): * tmp = PyMem_Malloc(self.view.itemsize) * if tmp == NULL: # <<<<<<<<<<<<<< * raise MemoryError * item = tmp */ - __pyx_t_1 = ((__pyx_v_tmp == NULL) != 0); - if (unlikely(__pyx_t_1)) { + __pyx_t_2 = ((__pyx_v_tmp == NULL) != 0); + if (unlikely(__pyx_t_2)) { - /* "View.MemoryView":457 + /* "View.MemoryView":461 * tmp = PyMem_Malloc(self.view.itemsize) * if tmp == NULL: * raise MemoryError # <<<<<<<<<<<<<< * item = tmp * else: */ - PyErr_NoMemory(); __PYX_ERR(1, 457, __pyx_L1_error) + PyErr_NoMemory(); __PYX_ERR(1, 461, __pyx_L1_error) - /* "View.MemoryView":456 + /* "View.MemoryView":460 * if self.view.itemsize > sizeof(array): * tmp = PyMem_Malloc(self.view.itemsize) * if tmp == NULL: # <<<<<<<<<<<<<< @@ -6287,7 +6341,7 @@ static PyObject *__pyx_memoryview_setitem_slice_assign_scalar(struct __pyx_memor */ } - /* "View.MemoryView":458 + /* "View.MemoryView":462 * if tmp == NULL: * raise MemoryError * item = tmp # <<<<<<<<<<<<<< @@ -6296,7 +6350,7 @@ static PyObject *__pyx_memoryview_setitem_slice_assign_scalar(struct __pyx_memor */ __pyx_v_item = __pyx_v_tmp; - /* "View.MemoryView":454 + /* "View.MemoryView":458 * dst_slice = get_slice_from_memview(dst, &tmp_slice) * * if self.view.itemsize > sizeof(array): # <<<<<<<<<<<<<< @@ -6306,7 +6360,7 @@ static PyObject *__pyx_memoryview_setitem_slice_assign_scalar(struct __pyx_memor goto __pyx_L3; } - /* "View.MemoryView":460 + /* "View.MemoryView":464 * item = tmp * else: * item = array # <<<<<<<<<<<<<< @@ -6318,7 +6372,7 @@ static PyObject *__pyx_memoryview_setitem_slice_assign_scalar(struct __pyx_memor } __pyx_L3:; - /* "View.MemoryView":462 + /* "View.MemoryView":466 * item = array * * try: # <<<<<<<<<<<<<< @@ -6327,17 +6381,17 @@ static PyObject *__pyx_memoryview_setitem_slice_assign_scalar(struct __pyx_memor */ /*try:*/ { - /* "View.MemoryView":463 + /* "View.MemoryView":467 * * try: * if self.dtype_is_object: # <<<<<<<<<<<<<< * ( item)[0] = value * else: */ - __pyx_t_1 = (__pyx_v_self->dtype_is_object != 0); - if (__pyx_t_1) { + __pyx_t_2 = (__pyx_v_self->dtype_is_object != 0); + if (__pyx_t_2) { - /* "View.MemoryView":464 + /* "View.MemoryView":468 * try: * if self.dtype_is_object: * ( item)[0] = value # <<<<<<<<<<<<<< @@ -6346,7 +6400,7 @@ static PyObject *__pyx_memoryview_setitem_slice_assign_scalar(struct __pyx_memor */ (((PyObject **)__pyx_v_item)[0]) = ((PyObject *)__pyx_v_value); - /* "View.MemoryView":463 + /* "View.MemoryView":467 * * try: * if self.dtype_is_object: # <<<<<<<<<<<<<< @@ -6356,7 +6410,7 @@ static PyObject *__pyx_memoryview_setitem_slice_assign_scalar(struct __pyx_memor goto __pyx_L8; } - /* "View.MemoryView":466 + /* "View.MemoryView":470 * ( item)[0] = value * else: * self.assign_item_from_object( item, value) # <<<<<<<<<<<<<< @@ -6364,34 +6418,34 @@ static PyObject *__pyx_memoryview_setitem_slice_assign_scalar(struct __pyx_memor * */ /*else*/ { - __pyx_t_2 = ((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_2)) __PYX_ERR(1, 466, __pyx_L6_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __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(1, 470, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; } __pyx_L8:; - /* "View.MemoryView":470 + /* "View.MemoryView":474 * * * 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_1 = ((__pyx_v_self->view.suboffsets != NULL) != 0); - if (__pyx_t_1) { + __pyx_t_2 = ((__pyx_v_self->view.suboffsets != NULL) != 0); + if (__pyx_t_2) { - /* "View.MemoryView":471 + /* "View.MemoryView":475 * * 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_2 = assert_direct_dimensions(__pyx_v_self->view.suboffsets, __pyx_v_self->view.ndim); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 471, __pyx_L6_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_3 = assert_direct_dimensions(__pyx_v_self->view.suboffsets, __pyx_v_self->view.ndim); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 475, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - /* "View.MemoryView":470 + /* "View.MemoryView":474 * * * if self.view.suboffsets != NULL: # <<<<<<<<<<<<<< @@ -6400,7 +6454,7 @@ static PyObject *__pyx_memoryview_setitem_slice_assign_scalar(struct __pyx_memor */ } - /* "View.MemoryView":472 + /* "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, # <<<<<<<<<<<<<< @@ -6410,7 +6464,7 @@ static PyObject *__pyx_memoryview_setitem_slice_assign_scalar(struct __pyx_memor __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":475 + /* "View.MemoryView":479 * item, self.dtype_is_object) * finally: * PyMem_Free(tmp) # <<<<<<<<<<<<<< @@ -6426,38 +6480,38 @@ static PyObject *__pyx_memoryview_setitem_slice_assign_scalar(struct __pyx_memor /*exception exit:*/{ __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign - __pyx_t_6 = 0; __pyx_t_7 = 0; __pyx_t_8 = 0; __pyx_t_9 = 0; __pyx_t_10 = 0; __pyx_t_11 = 0; - __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; - if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_9, &__pyx_t_10, &__pyx_t_11); - if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_6, &__pyx_t_7, &__pyx_t_8) < 0)) __Pyx_ErrFetch(&__pyx_t_6, &__pyx_t_7, &__pyx_t_8); - __Pyx_XGOTREF(__pyx_t_6); + __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_t_3 = __pyx_lineno; __pyx_t_4 = __pyx_clineno; __pyx_t_5 = __pyx_filename; + __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_9); __Pyx_XGIVEREF(__pyx_t_10); __Pyx_XGIVEREF(__pyx_t_11); - __Pyx_ExceptionReset(__pyx_t_9, __pyx_t_10, __pyx_t_11); + __Pyx_XGIVEREF(__pyx_t_12); + __Pyx_ExceptionReset(__pyx_t_10, __pyx_t_11, __pyx_t_12); } - __Pyx_XGIVEREF(__pyx_t_6); __Pyx_XGIVEREF(__pyx_t_7); __Pyx_XGIVEREF(__pyx_t_8); - __Pyx_ErrRestore(__pyx_t_6, __pyx_t_7, __pyx_t_8); - __pyx_t_6 = 0; __pyx_t_7 = 0; __pyx_t_8 = 0; __pyx_t_9 = 0; __pyx_t_10 = 0; __pyx_t_11 = 0; - __pyx_lineno = __pyx_t_3; __pyx_clineno = __pyx_t_4; __pyx_filename = __pyx_t_5; + __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":445 + /* "View.MemoryView":449 * src.ndim, dst.ndim, self.dtype_is_object) * * cdef setitem_slice_assign_scalar(self, memoryview dst, value): # <<<<<<<<<<<<<< @@ -6469,7 +6523,7 @@ static PyObject *__pyx_memoryview_setitem_slice_assign_scalar(struct __pyx_memor __pyx_r = Py_None; __Pyx_INCREF(Py_None); goto __pyx_L0; __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); + __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:; @@ -6478,7 +6532,7 @@ static PyObject *__pyx_memoryview_setitem_slice_assign_scalar(struct __pyx_memor return __pyx_r; } -/* "View.MemoryView":477 +/* "View.MemoryView":481 * PyMem_Free(tmp) * * cdef setitem_indexed(self, index, value): # <<<<<<<<<<<<<< @@ -6494,28 +6548,28 @@ static PyObject *__pyx_memoryview_setitem_indexed(struct __pyx_memoryview_obj *_ PyObject *__pyx_t_2 = NULL; __Pyx_RefNannySetupContext("setitem_indexed", 0); - /* "View.MemoryView":478 + /* "View.MemoryView":482 * * 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(1, 478, __pyx_L1_error) + __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(1, 482, __pyx_L1_error) __pyx_v_itemp = __pyx_t_1; - /* "View.MemoryView":479 + /* "View.MemoryView":483 * 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(1, 479, __pyx_L1_error) + __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(1, 483, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - /* "View.MemoryView":477 + /* "View.MemoryView":481 * PyMem_Free(tmp) * * cdef setitem_indexed(self, index, value): # <<<<<<<<<<<<<< @@ -6536,7 +6590,7 @@ static PyObject *__pyx_memoryview_setitem_indexed(struct __pyx_memoryview_obj *_ return __pyx_r; } -/* "View.MemoryView":481 +/* "View.MemoryView":485 * self.assign_item_from_object(itemp, value) * * cdef convert_item_to_object(self, char *itemp): # <<<<<<<<<<<<<< @@ -6563,31 +6617,31 @@ static PyObject *__pyx_memoryview_convert_item_to_object(struct __pyx_memoryview int __pyx_t_11; __Pyx_RefNannySetupContext("convert_item_to_object", 0); - /* "View.MemoryView":484 + /* "View.MemoryView":488 * """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(1, 484, __pyx_L1_error) + __pyx_t_1 = __Pyx_Import(__pyx_n_s_struct, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 488, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_v_struct = __pyx_t_1; __pyx_t_1 = 0; - /* "View.MemoryView":487 + /* "View.MemoryView":491 * 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(1, 487, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyBytes_FromStringAndSize(__pyx_v_itemp + 0, __pyx_v_self->view.itemsize - 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 491, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_v_bytesitem = ((PyObject*)__pyx_t_1); __pyx_t_1 = 0; - /* "View.MemoryView":488 + /* "View.MemoryView":492 * * bytesitem = itemp[:self.view.itemsize] * try: # <<<<<<<<<<<<<< @@ -6603,16 +6657,16 @@ static PyObject *__pyx_memoryview_convert_item_to_object(struct __pyx_memoryview __Pyx_XGOTREF(__pyx_t_4); /*try:*/ { - /* "View.MemoryView":489 + /* "View.MemoryView":493 * 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(1, 489, __pyx_L3_error) + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_struct, __pyx_n_s_unpack); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 493, __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(1, 489, __pyx_L3_error) + __pyx_t_6 = __Pyx_PyBytes_FromString(__pyx_v_self->view.format); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 493, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_6); __pyx_t_7 = NULL; __pyx_t_8 = 0; @@ -6629,7 +6683,7 @@ static PyObject *__pyx_memoryview_convert_item_to_object(struct __pyx_memoryview #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(1, 489, __pyx_L3_error) + __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(1, 493, __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; @@ -6638,14 +6692,14 @@ static PyObject *__pyx_memoryview_convert_item_to_object(struct __pyx_memoryview #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(1, 489, __pyx_L3_error) + __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(1, 493, __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(1, 489, __pyx_L3_error) + __pyx_t_9 = PyTuple_New(2+__pyx_t_8); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 493, __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; @@ -6656,7 +6710,7 @@ static PyObject *__pyx_memoryview_convert_item_to_object(struct __pyx_memoryview __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(1, 489, __pyx_L3_error) + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_9, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 493, __pyx_L3_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; } @@ -6664,7 +6718,7 @@ static PyObject *__pyx_memoryview_convert_item_to_object(struct __pyx_memoryview __pyx_v_result = __pyx_t_1; __pyx_t_1 = 0; - /* "View.MemoryView":488 + /* "View.MemoryView":492 * * bytesitem = itemp[:self.view.itemsize] * try: # <<<<<<<<<<<<<< @@ -6673,7 +6727,7 @@ static PyObject *__pyx_memoryview_convert_item_to_object(struct __pyx_memoryview */ } - /* "View.MemoryView":493 + /* "View.MemoryView":497 * raise ValueError("Unable to convert item to object") * else: * if len(self.view.format) == 1: # <<<<<<<<<<<<<< @@ -6685,7 +6739,7 @@ static PyObject *__pyx_memoryview_convert_item_to_object(struct __pyx_memoryview __pyx_t_11 = ((__pyx_t_10 == 1) != 0); if (__pyx_t_11) { - /* "View.MemoryView":494 + /* "View.MemoryView":498 * else: * if len(self.view.format) == 1: * return result[0] # <<<<<<<<<<<<<< @@ -6693,13 +6747,13 @@ static PyObject *__pyx_memoryview_convert_item_to_object(struct __pyx_memoryview * */ __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(1, 494, __pyx_L5_except_error) + __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(1, 498, __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":493 + /* "View.MemoryView":497 * raise ValueError("Unable to convert item to object") * else: * if len(self.view.format) == 1: # <<<<<<<<<<<<<< @@ -6708,7 +6762,7 @@ static PyObject *__pyx_memoryview_convert_item_to_object(struct __pyx_memoryview */ } - /* "View.MemoryView":495 + /* "View.MemoryView":499 * if len(self.view.format) == 1: * return result[0] * return result # <<<<<<<<<<<<<< @@ -6727,7 +6781,7 @@ static PyObject *__pyx_memoryview_convert_item_to_object(struct __pyx_memoryview __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; - /* "View.MemoryView":490 + /* "View.MemoryView":494 * try: * result = struct.unpack(self.view.format, bytesitem) * except struct.error: # <<<<<<<<<<<<<< @@ -6735,7 +6789,7 @@ static PyObject *__pyx_memoryview_convert_item_to_object(struct __pyx_memoryview * 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(1, 490, __pyx_L5_except_error) + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_struct, __pyx_n_s_error); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 494, __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; @@ -6743,28 +6797,28 @@ static PyObject *__pyx_memoryview_convert_item_to_object(struct __pyx_memoryview __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(1, 490, __pyx_L5_except_error) + if (__Pyx_GetException(&__pyx_t_9, &__pyx_t_5, &__pyx_t_1) < 0) __PYX_ERR(1, 494, __pyx_L5_except_error) __Pyx_GOTREF(__pyx_t_9); __Pyx_GOTREF(__pyx_t_5); __Pyx_GOTREF(__pyx_t_1); - /* "View.MemoryView":491 + /* "View.MemoryView":495 * 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__9, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 491, __pyx_L5_except_error) + __pyx_t_6 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__9, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 495, __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(1, 491, __pyx_L5_except_error) + __PYX_ERR(1, 495, __pyx_L5_except_error) } goto __pyx_L5_except_error; __pyx_L5_except_error:; - /* "View.MemoryView":488 + /* "View.MemoryView":492 * * bytesitem = itemp[:self.view.itemsize] * try: # <<<<<<<<<<<<<< @@ -6784,7 +6838,7 @@ static PyObject *__pyx_memoryview_convert_item_to_object(struct __pyx_memoryview goto __pyx_L0; } - /* "View.MemoryView":481 + /* "View.MemoryView":485 * self.assign_item_from_object(itemp, value) * * cdef convert_item_to_object(self, char *itemp): # <<<<<<<<<<<<<< @@ -6810,7 +6864,7 @@ static PyObject *__pyx_memoryview_convert_item_to_object(struct __pyx_memoryview return __pyx_r; } -/* "View.MemoryView":497 +/* "View.MemoryView":501 * return result * * cdef assign_item_from_object(self, char *itemp, object value): # <<<<<<<<<<<<<< @@ -6841,19 +6895,19 @@ static PyObject *__pyx_memoryview_assign_item_from_object(struct __pyx_memoryvie char *__pyx_t_14; __Pyx_RefNannySetupContext("assign_item_from_object", 0); - /* "View.MemoryView":500 + /* "View.MemoryView":504 * """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(1, 500, __pyx_L1_error) + __pyx_t_1 = __Pyx_Import(__pyx_n_s_struct, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 504, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_v_struct = __pyx_t_1; __pyx_t_1 = 0; - /* "View.MemoryView":505 + /* "View.MemoryView":509 * cdef Py_ssize_t i * * if isinstance(value, tuple): # <<<<<<<<<<<<<< @@ -6864,37 +6918,37 @@ static PyObject *__pyx_memoryview_assign_item_from_object(struct __pyx_memoryvie __pyx_t_3 = (__pyx_t_2 != 0); if (__pyx_t_3) { - /* "View.MemoryView":506 + /* "View.MemoryView":510 * * 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(1, 506, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_struct, __pyx_n_s_pack); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 510, __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(1, 506, __pyx_L1_error) + __pyx_t_4 = __Pyx_PyBytes_FromString(__pyx_v_self->view.format); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 510, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); - __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 506, __pyx_L1_error) + __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 510, __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(1, 506, __pyx_L1_error) + __pyx_t_4 = __Pyx_PySequence_Tuple(__pyx_v_value); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 510, __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(1, 506, __pyx_L1_error) + __pyx_t_6 = PyNumber_Add(__pyx_t_5, __pyx_t_4); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 510, __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(1, 506, __pyx_L1_error) + __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_6, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 510, __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)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "bytes", Py_TYPE(__pyx_t_4)->tp_name), 0))) __PYX_ERR(1, 506, __pyx_L1_error) + if (!(likely(PyBytes_CheckExact(__pyx_t_4))||((__pyx_t_4) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "bytes", Py_TYPE(__pyx_t_4)->tp_name), 0))) __PYX_ERR(1, 510, __pyx_L1_error) __pyx_v_bytesvalue = ((PyObject*)__pyx_t_4); __pyx_t_4 = 0; - /* "View.MemoryView":505 + /* "View.MemoryView":509 * cdef Py_ssize_t i * * if isinstance(value, tuple): # <<<<<<<<<<<<<< @@ -6904,7 +6958,7 @@ static PyObject *__pyx_memoryview_assign_item_from_object(struct __pyx_memoryvie goto __pyx_L3; } - /* "View.MemoryView":508 + /* "View.MemoryView":512 * bytesvalue = struct.pack(self.view.format, *value) * else: * bytesvalue = struct.pack(self.view.format, value) # <<<<<<<<<<<<<< @@ -6912,9 +6966,9 @@ static PyObject *__pyx_memoryview_assign_item_from_object(struct __pyx_memoryvie * 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(1, 508, __pyx_L1_error) + __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_struct, __pyx_n_s_pack); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 512, __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(1, 508, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyBytes_FromString(__pyx_v_self->view.format); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 512, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_5 = NULL; __pyx_t_7 = 0; @@ -6931,7 +6985,7 @@ static PyObject *__pyx_memoryview_assign_item_from_object(struct __pyx_memoryvie #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(1, 508, __pyx_L1_error) + __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(1, 512, __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; @@ -6940,14 +6994,14 @@ static PyObject *__pyx_memoryview_assign_item_from_object(struct __pyx_memoryvie #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(1, 508, __pyx_L1_error) + __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(1, 512, __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(1, 508, __pyx_L1_error) + __pyx_t_8 = PyTuple_New(2+__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 512, __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; @@ -6958,18 +7012,18 @@ static PyObject *__pyx_memoryview_assign_item_from_object(struct __pyx_memoryvie __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(1, 508, __pyx_L1_error) + __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_8, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 512, __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)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "bytes", Py_TYPE(__pyx_t_4)->tp_name), 0))) __PYX_ERR(1, 508, __pyx_L1_error) + if (!(likely(PyBytes_CheckExact(__pyx_t_4))||((__pyx_t_4) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "bytes", Py_TYPE(__pyx_t_4)->tp_name), 0))) __PYX_ERR(1, 512, __pyx_L1_error) __pyx_v_bytesvalue = ((PyObject*)__pyx_t_4); __pyx_t_4 = 0; } __pyx_L3:; - /* "View.MemoryView":510 + /* "View.MemoryView":514 * bytesvalue = struct.pack(self.view.format, value) * * for i, c in enumerate(bytesvalue): # <<<<<<<<<<<<<< @@ -6979,7 +7033,7 @@ static PyObject *__pyx_memoryview_assign_item_from_object(struct __pyx_memoryvie __pyx_t_9 = 0; if (unlikely(__pyx_v_bytesvalue == Py_None)) { PyErr_SetString(PyExc_TypeError, "'NoneType' is not iterable"); - __PYX_ERR(1, 510, __pyx_L1_error) + __PYX_ERR(1, 514, __pyx_L1_error) } __Pyx_INCREF(__pyx_v_bytesvalue); __pyx_t_10 = __pyx_v_bytesvalue; @@ -6989,7 +7043,7 @@ static PyObject *__pyx_memoryview_assign_item_from_object(struct __pyx_memoryvie __pyx_t_11 = __pyx_t_14; __pyx_v_c = (__pyx_t_11[0]); - /* "View.MemoryView":511 + /* "View.MemoryView":515 * * for i, c in enumerate(bytesvalue): * itemp[i] = c # <<<<<<<<<<<<<< @@ -6998,7 +7052,7 @@ static PyObject *__pyx_memoryview_assign_item_from_object(struct __pyx_memoryvie */ __pyx_v_i = __pyx_t_9; - /* "View.MemoryView":510 + /* "View.MemoryView":514 * bytesvalue = struct.pack(self.view.format, value) * * for i, c in enumerate(bytesvalue): # <<<<<<<<<<<<<< @@ -7007,7 +7061,7 @@ static PyObject *__pyx_memoryview_assign_item_from_object(struct __pyx_memoryvie */ __pyx_t_9 = (__pyx_t_9 + 1); - /* "View.MemoryView":511 + /* "View.MemoryView":515 * * for i, c in enumerate(bytesvalue): * itemp[i] = c # <<<<<<<<<<<<<< @@ -7018,7 +7072,7 @@ static PyObject *__pyx_memoryview_assign_item_from_object(struct __pyx_memoryvie } __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; - /* "View.MemoryView":497 + /* "View.MemoryView":501 * return result * * cdef assign_item_from_object(self, char *itemp, object value): # <<<<<<<<<<<<<< @@ -7046,7 +7100,7 @@ static PyObject *__pyx_memoryview_assign_item_from_object(struct __pyx_memoryvie return __pyx_r; } -/* "View.MemoryView":514 +/* "View.MemoryView":518 * * @cname('getbuffer') * def __getbuffer__(self, Py_buffer *info, int flags): # <<<<<<<<<<<<<< @@ -7086,7 +7140,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu __pyx_v_info->obj = Py_None; __Pyx_INCREF(Py_None); __Pyx_GIVEREF(__pyx_v_info->obj); - /* "View.MemoryView":515 + /* "View.MemoryView":519 * @cname('getbuffer') * def __getbuffer__(self, Py_buffer *info, int flags): * if flags & PyBUF_WRITABLE and self.view.readonly: # <<<<<<<<<<<<<< @@ -7104,20 +7158,20 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu __pyx_L4_bool_binop_done:; if (unlikely(__pyx_t_1)) { - /* "View.MemoryView":516 + /* "View.MemoryView":520 * 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__10, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 516, __pyx_L1_error) + __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__10, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 520, __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(1, 516, __pyx_L1_error) + __PYX_ERR(1, 520, __pyx_L1_error) - /* "View.MemoryView":515 + /* "View.MemoryView":519 * @cname('getbuffer') * def __getbuffer__(self, Py_buffer *info, int flags): * if flags & PyBUF_WRITABLE and self.view.readonly: # <<<<<<<<<<<<<< @@ -7126,7 +7180,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu */ } - /* "View.MemoryView":518 + /* "View.MemoryView":522 * raise ValueError("Cannot create writable memory view from read-only memoryview") * * if flags & PyBUF_ND: # <<<<<<<<<<<<<< @@ -7136,7 +7190,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu __pyx_t_1 = ((__pyx_v_flags & PyBUF_ND) != 0); if (__pyx_t_1) { - /* "View.MemoryView":519 + /* "View.MemoryView":523 * * if flags & PyBUF_ND: * info.shape = self.view.shape # <<<<<<<<<<<<<< @@ -7146,7 +7200,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu __pyx_t_4 = __pyx_v_self->view.shape; __pyx_v_info->shape = __pyx_t_4; - /* "View.MemoryView":518 + /* "View.MemoryView":522 * raise ValueError("Cannot create writable memory view from read-only memoryview") * * if flags & PyBUF_ND: # <<<<<<<<<<<<<< @@ -7156,7 +7210,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu goto __pyx_L6; } - /* "View.MemoryView":521 + /* "View.MemoryView":525 * info.shape = self.view.shape * else: * info.shape = NULL # <<<<<<<<<<<<<< @@ -7168,7 +7222,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu } __pyx_L6:; - /* "View.MemoryView":523 + /* "View.MemoryView":527 * info.shape = NULL * * if flags & PyBUF_STRIDES: # <<<<<<<<<<<<<< @@ -7178,7 +7232,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu __pyx_t_1 = ((__pyx_v_flags & PyBUF_STRIDES) != 0); if (__pyx_t_1) { - /* "View.MemoryView":524 + /* "View.MemoryView":528 * * if flags & PyBUF_STRIDES: * info.strides = self.view.strides # <<<<<<<<<<<<<< @@ -7188,7 +7242,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu __pyx_t_4 = __pyx_v_self->view.strides; __pyx_v_info->strides = __pyx_t_4; - /* "View.MemoryView":523 + /* "View.MemoryView":527 * info.shape = NULL * * if flags & PyBUF_STRIDES: # <<<<<<<<<<<<<< @@ -7198,7 +7252,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu goto __pyx_L7; } - /* "View.MemoryView":526 + /* "View.MemoryView":530 * info.strides = self.view.strides * else: * info.strides = NULL # <<<<<<<<<<<<<< @@ -7210,7 +7264,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu } __pyx_L7:; - /* "View.MemoryView":528 + /* "View.MemoryView":532 * info.strides = NULL * * if flags & PyBUF_INDIRECT: # <<<<<<<<<<<<<< @@ -7220,7 +7274,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu __pyx_t_1 = ((__pyx_v_flags & PyBUF_INDIRECT) != 0); if (__pyx_t_1) { - /* "View.MemoryView":529 + /* "View.MemoryView":533 * * if flags & PyBUF_INDIRECT: * info.suboffsets = self.view.suboffsets # <<<<<<<<<<<<<< @@ -7230,7 +7284,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu __pyx_t_4 = __pyx_v_self->view.suboffsets; __pyx_v_info->suboffsets = __pyx_t_4; - /* "View.MemoryView":528 + /* "View.MemoryView":532 * info.strides = NULL * * if flags & PyBUF_INDIRECT: # <<<<<<<<<<<<<< @@ -7240,7 +7294,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu goto __pyx_L8; } - /* "View.MemoryView":531 + /* "View.MemoryView":535 * info.suboffsets = self.view.suboffsets * else: * info.suboffsets = NULL # <<<<<<<<<<<<<< @@ -7252,7 +7306,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu } __pyx_L8:; - /* "View.MemoryView":533 + /* "View.MemoryView":537 * info.suboffsets = NULL * * if flags & PyBUF_FORMAT: # <<<<<<<<<<<<<< @@ -7262,7 +7316,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu __pyx_t_1 = ((__pyx_v_flags & PyBUF_FORMAT) != 0); if (__pyx_t_1) { - /* "View.MemoryView":534 + /* "View.MemoryView":538 * * if flags & PyBUF_FORMAT: * info.format = self.view.format # <<<<<<<<<<<<<< @@ -7272,7 +7326,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu __pyx_t_5 = __pyx_v_self->view.format; __pyx_v_info->format = __pyx_t_5; - /* "View.MemoryView":533 + /* "View.MemoryView":537 * info.suboffsets = NULL * * if flags & PyBUF_FORMAT: # <<<<<<<<<<<<<< @@ -7282,7 +7336,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu goto __pyx_L9; } - /* "View.MemoryView":536 + /* "View.MemoryView":540 * info.format = self.view.format * else: * info.format = NULL # <<<<<<<<<<<<<< @@ -7294,7 +7348,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu } __pyx_L9:; - /* "View.MemoryView":538 + /* "View.MemoryView":542 * info.format = NULL * * info.buf = self.view.buf # <<<<<<<<<<<<<< @@ -7304,7 +7358,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu __pyx_t_6 = __pyx_v_self->view.buf; __pyx_v_info->buf = __pyx_t_6; - /* "View.MemoryView":539 + /* "View.MemoryView":543 * * info.buf = self.view.buf * info.ndim = self.view.ndim # <<<<<<<<<<<<<< @@ -7314,7 +7368,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu __pyx_t_7 = __pyx_v_self->view.ndim; __pyx_v_info->ndim = __pyx_t_7; - /* "View.MemoryView":540 + /* "View.MemoryView":544 * info.buf = self.view.buf * info.ndim = self.view.ndim * info.itemsize = self.view.itemsize # <<<<<<<<<<<<<< @@ -7324,7 +7378,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu __pyx_t_8 = __pyx_v_self->view.itemsize; __pyx_v_info->itemsize = __pyx_t_8; - /* "View.MemoryView":541 + /* "View.MemoryView":545 * info.ndim = self.view.ndim * info.itemsize = self.view.itemsize * info.len = self.view.len # <<<<<<<<<<<<<< @@ -7334,7 +7388,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu __pyx_t_8 = __pyx_v_self->view.len; __pyx_v_info->len = __pyx_t_8; - /* "View.MemoryView":542 + /* "View.MemoryView":546 * info.itemsize = self.view.itemsize * info.len = self.view.len * info.readonly = self.view.readonly # <<<<<<<<<<<<<< @@ -7344,7 +7398,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu __pyx_t_1 = __pyx_v_self->view.readonly; __pyx_v_info->readonly = __pyx_t_1; - /* "View.MemoryView":543 + /* "View.MemoryView":547 * info.len = self.view.len * info.readonly = self.view.readonly * info.obj = self # <<<<<<<<<<<<<< @@ -7357,7 +7411,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = ((PyObject *)__pyx_v_self); - /* "View.MemoryView":514 + /* "View.MemoryView":518 * * @cname('getbuffer') * def __getbuffer__(self, Py_buffer *info, int flags): # <<<<<<<<<<<<<< @@ -7387,7 +7441,7 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu return __pyx_r; } -/* "View.MemoryView":549 +/* "View.MemoryView":553 * * @property * def T(self): # <<<<<<<<<<<<<< @@ -7416,29 +7470,29 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_1T___get__(struct _ int __pyx_t_2; __Pyx_RefNannySetupContext("__get__", 0); - /* "View.MemoryView":550 + /* "View.MemoryView":554 * @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(1, 550, __pyx_L1_error) + __pyx_t_1 = __pyx_memoryview_copy_object(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 554, __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(1, 550, __pyx_L1_error) + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_memoryviewslice_type))))) __PYX_ERR(1, 554, __pyx_L1_error) __pyx_v_result = ((struct __pyx_memoryviewslice_obj *)__pyx_t_1); __pyx_t_1 = 0; - /* "View.MemoryView":551 + /* "View.MemoryView":555 * 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(1, 551, __pyx_L1_error) + __pyx_t_2 = __pyx_memslice_transpose((&__pyx_v_result->from_slice)); if (unlikely(__pyx_t_2 == ((int)0))) __PYX_ERR(1, 555, __pyx_L1_error) - /* "View.MemoryView":552 + /* "View.MemoryView":556 * cdef _memoryviewslice result = memoryview_copy(self) * transpose_memslice(&result.from_slice) * return result # <<<<<<<<<<<<<< @@ -7450,7 +7504,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_1T___get__(struct _ __pyx_r = ((PyObject *)__pyx_v_result); goto __pyx_L0; - /* "View.MemoryView":549 + /* "View.MemoryView":553 * * @property * def T(self): # <<<<<<<<<<<<<< @@ -7470,7 +7524,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_1T___get__(struct _ return __pyx_r; } -/* "View.MemoryView":555 +/* "View.MemoryView":559 * * @property * def base(self): # <<<<<<<<<<<<<< @@ -7496,7 +7550,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4base___get__(struc __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__get__", 0); - /* "View.MemoryView":556 + /* "View.MemoryView":560 * @property * def base(self): * return self.obj # <<<<<<<<<<<<<< @@ -7508,7 +7562,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4base___get__(struc __pyx_r = __pyx_v_self->obj; goto __pyx_L0; - /* "View.MemoryView":555 + /* "View.MemoryView":559 * * @property * def base(self): # <<<<<<<<<<<<<< @@ -7523,7 +7577,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4base___get__(struc return __pyx_r; } -/* "View.MemoryView":559 +/* "View.MemoryView":563 * * @property * def shape(self): # <<<<<<<<<<<<<< @@ -7555,7 +7609,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_5shape___get__(stru PyObject *__pyx_t_5 = NULL; __Pyx_RefNannySetupContext("__get__", 0); - /* "View.MemoryView":560 + /* "View.MemoryView":564 * @property * def shape(self): * return tuple([length for length in self.view.shape[:self.view.ndim]]) # <<<<<<<<<<<<<< @@ -7563,25 +7617,25 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_5shape___get__(stru * @property */ __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 560, __pyx_L1_error) + __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 564, __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(1, 560, __pyx_L1_error) + __pyx_t_5 = PyInt_FromSsize_t(__pyx_v_length); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 564, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_5); - if (unlikely(__Pyx_ListComp_Append(__pyx_t_1, (PyObject*)__pyx_t_5))) __PYX_ERR(1, 560, __pyx_L1_error) + if (unlikely(__Pyx_ListComp_Append(__pyx_t_1, (PyObject*)__pyx_t_5))) __PYX_ERR(1, 564, __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(1, 560, __pyx_L1_error) + __pyx_t_5 = PyList_AsTuple(((PyObject*)__pyx_t_1)); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 564, __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":559 + /* "View.MemoryView":563 * * @property * def shape(self): # <<<<<<<<<<<<<< @@ -7601,7 +7655,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_5shape___get__(stru return __pyx_r; } -/* "View.MemoryView":563 +/* "View.MemoryView":567 * * @property * def strides(self): # <<<<<<<<<<<<<< @@ -7634,7 +7688,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_7strides___get__(st PyObject *__pyx_t_6 = NULL; __Pyx_RefNannySetupContext("__get__", 0); - /* "View.MemoryView":564 + /* "View.MemoryView":568 * @property * def strides(self): * if self.view.strides == NULL: # <<<<<<<<<<<<<< @@ -7644,20 +7698,20 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_7strides___get__(st __pyx_t_1 = ((__pyx_v_self->view.strides == NULL) != 0); if (unlikely(__pyx_t_1)) { - /* "View.MemoryView":566 + /* "View.MemoryView":570 * 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__11, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 566, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__11, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 570, __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(1, 566, __pyx_L1_error) + __PYX_ERR(1, 570, __pyx_L1_error) - /* "View.MemoryView":564 + /* "View.MemoryView":568 * @property * def strides(self): * if self.view.strides == NULL: # <<<<<<<<<<<<<< @@ -7666,7 +7720,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_7strides___get__(st */ } - /* "View.MemoryView":568 + /* "View.MemoryView":572 * raise ValueError("Buffer view does not expose strides") * * return tuple([stride for stride in self.view.strides[:self.view.ndim]]) # <<<<<<<<<<<<<< @@ -7674,25 +7728,25 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_7strides___get__(st * @property */ __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = PyList_New(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 568, __pyx_L1_error) + __pyx_t_2 = PyList_New(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 572, __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(1, 568, __pyx_L1_error) + __pyx_t_6 = PyInt_FromSsize_t(__pyx_v_stride); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 572, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_6); - if (unlikely(__Pyx_ListComp_Append(__pyx_t_2, (PyObject*)__pyx_t_6))) __PYX_ERR(1, 568, __pyx_L1_error) + if (unlikely(__Pyx_ListComp_Append(__pyx_t_2, (PyObject*)__pyx_t_6))) __PYX_ERR(1, 572, __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(1, 568, __pyx_L1_error) + __pyx_t_6 = PyList_AsTuple(((PyObject*)__pyx_t_2)); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 572, __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":563 + /* "View.MemoryView":567 * * @property * def strides(self): # <<<<<<<<<<<<<< @@ -7712,7 +7766,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_7strides___get__(st return __pyx_r; } -/* "View.MemoryView":571 +/* "View.MemoryView":575 * * @property * def suboffsets(self): # <<<<<<<<<<<<<< @@ -7745,7 +7799,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_10suboffsets___get_ Py_ssize_t *__pyx_t_6; __Pyx_RefNannySetupContext("__get__", 0); - /* "View.MemoryView":572 + /* "View.MemoryView":576 * @property * def suboffsets(self): * if self.view.suboffsets == NULL: # <<<<<<<<<<<<<< @@ -7755,7 +7809,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_10suboffsets___get_ __pyx_t_1 = ((__pyx_v_self->view.suboffsets == NULL) != 0); if (__pyx_t_1) { - /* "View.MemoryView":573 + /* "View.MemoryView":577 * def suboffsets(self): * if self.view.suboffsets == NULL: * return (-1,) * self.view.ndim # <<<<<<<<<<<<<< @@ -7763,16 +7817,16 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_10suboffsets___get_ * 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(1, 573, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_self->view.ndim); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 577, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyNumber_Multiply(__pyx_tuple__12, __pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 573, __pyx_L1_error) + __pyx_t_3 = PyNumber_Multiply(__pyx_tuple__12, __pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 577, __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":572 + /* "View.MemoryView":576 * @property * def suboffsets(self): * if self.view.suboffsets == NULL: # <<<<<<<<<<<<<< @@ -7781,7 +7835,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_10suboffsets___get_ */ } - /* "View.MemoryView":575 + /* "View.MemoryView":579 * return (-1,) * self.view.ndim * * return tuple([suboffset for suboffset in self.view.suboffsets[:self.view.ndim]]) # <<<<<<<<<<<<<< @@ -7789,25 +7843,25 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_10suboffsets___get_ * @property */ __Pyx_XDECREF(__pyx_r); - __pyx_t_3 = PyList_New(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 575, __pyx_L1_error) + __pyx_t_3 = PyList_New(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 579, __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(1, 575, __pyx_L1_error) + __pyx_t_2 = PyInt_FromSsize_t(__pyx_v_suboffset); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 579, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); - if (unlikely(__Pyx_ListComp_Append(__pyx_t_3, (PyObject*)__pyx_t_2))) __PYX_ERR(1, 575, __pyx_L1_error) + if (unlikely(__Pyx_ListComp_Append(__pyx_t_3, (PyObject*)__pyx_t_2))) __PYX_ERR(1, 579, __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(1, 575, __pyx_L1_error) + __pyx_t_2 = PyList_AsTuple(((PyObject*)__pyx_t_3)); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 579, __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":571 + /* "View.MemoryView":575 * * @property * def suboffsets(self): # <<<<<<<<<<<<<< @@ -7827,7 +7881,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_10suboffsets___get_ return __pyx_r; } -/* "View.MemoryView":578 +/* "View.MemoryView":582 * * @property * def ndim(self): # <<<<<<<<<<<<<< @@ -7854,7 +7908,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4ndim___get__(struc PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("__get__", 0); - /* "View.MemoryView":579 + /* "View.MemoryView":583 * @property * def ndim(self): * return self.view.ndim # <<<<<<<<<<<<<< @@ -7862,13 +7916,13 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4ndim___get__(struc * @property */ __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->view.ndim); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 579, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->view.ndim); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 583, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; - /* "View.MemoryView":578 + /* "View.MemoryView":582 * * @property * def ndim(self): # <<<<<<<<<<<<<< @@ -7887,7 +7941,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4ndim___get__(struc return __pyx_r; } -/* "View.MemoryView":582 +/* "View.MemoryView":586 * * @property * def itemsize(self): # <<<<<<<<<<<<<< @@ -7914,7 +7968,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_8itemsize___get__(s PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("__get__", 0); - /* "View.MemoryView":583 + /* "View.MemoryView":587 * @property * def itemsize(self): * return self.view.itemsize # <<<<<<<<<<<<<< @@ -7922,13 +7976,13 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_8itemsize___get__(s * @property */ __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PyInt_FromSsize_t(__pyx_v_self->view.itemsize); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 583, __pyx_L1_error) + __pyx_t_1 = PyInt_FromSsize_t(__pyx_v_self->view.itemsize); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 587, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; - /* "View.MemoryView":582 + /* "View.MemoryView":586 * * @property * def itemsize(self): # <<<<<<<<<<<<<< @@ -7947,7 +8001,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_8itemsize___get__(s return __pyx_r; } -/* "View.MemoryView":586 +/* "View.MemoryView":590 * * @property * def nbytes(self): # <<<<<<<<<<<<<< @@ -7976,7 +8030,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_6nbytes___get__(str PyObject *__pyx_t_3 = NULL; __Pyx_RefNannySetupContext("__get__", 0); - /* "View.MemoryView":587 + /* "View.MemoryView":591 * @property * def nbytes(self): * return self.size * self.view.itemsize # <<<<<<<<<<<<<< @@ -7984,11 +8038,11 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_6nbytes___get__(str * @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(1, 587, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_size); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 591, __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(1, 587, __pyx_L1_error) + __pyx_t_2 = PyInt_FromSsize_t(__pyx_v_self->view.itemsize); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 591, __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(1, 587, __pyx_L1_error) + __pyx_t_3 = PyNumber_Multiply(__pyx_t_1, __pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 591, __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; @@ -7996,7 +8050,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_6nbytes___get__(str __pyx_t_3 = 0; goto __pyx_L0; - /* "View.MemoryView":586 + /* "View.MemoryView":590 * * @property * def nbytes(self): # <<<<<<<<<<<<<< @@ -8017,7 +8071,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_6nbytes___get__(str return __pyx_r; } -/* "View.MemoryView":590 +/* "View.MemoryView":594 * * @property * def size(self): # <<<<<<<<<<<<<< @@ -8051,7 +8105,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4size___get__(struc PyObject *__pyx_t_6 = NULL; __Pyx_RefNannySetupContext("__get__", 0); - /* "View.MemoryView":591 + /* "View.MemoryView":595 * @property * def size(self): * if self._size is None: # <<<<<<<<<<<<<< @@ -8062,7 +8116,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4size___get__(struc __pyx_t_2 = (__pyx_t_1 != 0); if (__pyx_t_2) { - /* "View.MemoryView":592 + /* "View.MemoryView":596 * def size(self): * if self._size is None: * result = 1 # <<<<<<<<<<<<<< @@ -8072,7 +8126,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4size___get__(struc __Pyx_INCREF(__pyx_int_1); __pyx_v_result = __pyx_int_1; - /* "View.MemoryView":594 + /* "View.MemoryView":598 * result = 1 * * for length in self.view.shape[:self.view.ndim]: # <<<<<<<<<<<<<< @@ -8082,25 +8136,25 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4size___get__(struc __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(1, 594, __pyx_L1_error) + __pyx_t_6 = PyInt_FromSsize_t((__pyx_t_3[0])); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 598, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_6); __Pyx_XDECREF_SET(__pyx_v_length, __pyx_t_6); __pyx_t_6 = 0; - /* "View.MemoryView":595 + /* "View.MemoryView":599 * * 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(1, 595, __pyx_L1_error) + __pyx_t_6 = PyNumber_InPlaceMultiply(__pyx_v_result, __pyx_v_length); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 599, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_6); __Pyx_DECREF_SET(__pyx_v_result, __pyx_t_6); __pyx_t_6 = 0; } - /* "View.MemoryView":597 + /* "View.MemoryView":601 * result *= length * * self._size = result # <<<<<<<<<<<<<< @@ -8113,7 +8167,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4size___get__(struc __Pyx_DECREF(__pyx_v_self->_size); __pyx_v_self->_size = __pyx_v_result; - /* "View.MemoryView":591 + /* "View.MemoryView":595 * @property * def size(self): * if self._size is None: # <<<<<<<<<<<<<< @@ -8122,7 +8176,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4size___get__(struc */ } - /* "View.MemoryView":599 + /* "View.MemoryView":603 * self._size = result * * return self._size # <<<<<<<<<<<<<< @@ -8134,7 +8188,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4size___get__(struc __pyx_r = __pyx_v_self->_size; goto __pyx_L0; - /* "View.MemoryView":590 + /* "View.MemoryView":594 * * @property * def size(self): # <<<<<<<<<<<<<< @@ -8155,7 +8209,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4size___get__(struc return __pyx_r; } -/* "View.MemoryView":601 +/* "View.MemoryView":605 * return self._size * * def __len__(self): # <<<<<<<<<<<<<< @@ -8182,7 +8236,7 @@ static Py_ssize_t __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_1 int __pyx_t_1; __Pyx_RefNannySetupContext("__len__", 0); - /* "View.MemoryView":602 + /* "View.MemoryView":606 * * def __len__(self): * if self.view.ndim >= 1: # <<<<<<<<<<<<<< @@ -8192,7 +8246,7 @@ static Py_ssize_t __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_1 __pyx_t_1 = ((__pyx_v_self->view.ndim >= 1) != 0); if (__pyx_t_1) { - /* "View.MemoryView":603 + /* "View.MemoryView":607 * def __len__(self): * if self.view.ndim >= 1: * return self.view.shape[0] # <<<<<<<<<<<<<< @@ -8202,7 +8256,7 @@ static Py_ssize_t __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_1 __pyx_r = (__pyx_v_self->view.shape[0]); goto __pyx_L0; - /* "View.MemoryView":602 + /* "View.MemoryView":606 * * def __len__(self): * if self.view.ndim >= 1: # <<<<<<<<<<<<<< @@ -8211,7 +8265,7 @@ static Py_ssize_t __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_1 */ } - /* "View.MemoryView":605 + /* "View.MemoryView":609 * return self.view.shape[0] * * return 0 # <<<<<<<<<<<<<< @@ -8221,7 +8275,7 @@ static Py_ssize_t __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_1 __pyx_r = 0; goto __pyx_L0; - /* "View.MemoryView":601 + /* "View.MemoryView":605 * return self._size * * def __len__(self): # <<<<<<<<<<<<<< @@ -8235,7 +8289,7 @@ static Py_ssize_t __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_1 return __pyx_r; } -/* "View.MemoryView":607 +/* "View.MemoryView":611 * return 0 * * def __repr__(self): # <<<<<<<<<<<<<< @@ -8264,7 +8318,7 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_12 PyObject *__pyx_t_3 = NULL; __Pyx_RefNannySetupContext("__repr__", 0); - /* "View.MemoryView":608 + /* "View.MemoryView":612 * * def __repr__(self): * return "" % (self.base.__class__.__name__, # <<<<<<<<<<<<<< @@ -8272,33 +8326,33 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_12 * */ __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(1, 608, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_base); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 612, __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(1, 608, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_class); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 612, __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(1, 608, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_name_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 612, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - /* "View.MemoryView":609 + /* "View.MemoryView":613 * 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(1, 609, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 613, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); - /* "View.MemoryView":608 + /* "View.MemoryView":612 * * def __repr__(self): * return "" % (self.base.__class__.__name__, # <<<<<<<<<<<<<< * id(self)) * */ - __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 608, __pyx_L1_error) + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 612, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_GIVEREF(__pyx_t_1); PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1); @@ -8306,14 +8360,14 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_12 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(1, 608, __pyx_L1_error) + __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(1, 612, __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":607 + /* "View.MemoryView":611 * return 0 * * def __repr__(self): # <<<<<<<<<<<<<< @@ -8334,7 +8388,7 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_12 return __pyx_r; } -/* "View.MemoryView":611 +/* "View.MemoryView":615 * id(self)) * * def __str__(self): # <<<<<<<<<<<<<< @@ -8362,7 +8416,7 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_14 PyObject *__pyx_t_2 = NULL; __Pyx_RefNannySetupContext("__str__", 0); - /* "View.MemoryView":612 + /* "View.MemoryView":616 * * def __str__(self): * return "" % (self.base.__class__.__name__,) # <<<<<<<<<<<<<< @@ -8370,27 +8424,27 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_14 * */ __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(1, 612, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_base); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 616, __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(1, 612, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_class); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 616, __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(1, 612, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_name_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 616, __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(1, 612, __pyx_L1_error) + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 616, __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(1, 612, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyString_Format(__pyx_kp_s_MemoryView_of_r_object, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 616, __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":611 + /* "View.MemoryView":615 * id(self)) * * def __str__(self): # <<<<<<<<<<<<<< @@ -8410,7 +8464,7 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_14 return __pyx_r; } -/* "View.MemoryView":615 +/* "View.MemoryView":619 * * * def is_c_contig(self): # <<<<<<<<<<<<<< @@ -8436,19 +8490,21 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_16 __Pyx_memviewslice __pyx_v_tmp; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; + __Pyx_memviewslice *__pyx_t_1; + PyObject *__pyx_t_2 = NULL; __Pyx_RefNannySetupContext("is_c_contig", 0); - /* "View.MemoryView":618 + /* "View.MemoryView":622 * 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_v_mslice = __pyx_memoryview_get_slice_from_memoryview(__pyx_v_self, (&__pyx_v_tmp)); + __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(1, 622, __pyx_L1_error) + __pyx_v_mslice = __pyx_t_1; - /* "View.MemoryView":619 + /* "View.MemoryView":623 * cdef __Pyx_memviewslice tmp * mslice = get_slice_from_memview(self, &tmp) * return slice_is_contig(mslice[0], 'C', self.view.ndim) # <<<<<<<<<<<<<< @@ -8456,13 +8512,13 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_16 * def is_f_contig(self): */ __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_memviewslice_is_contig((__pyx_v_mslice[0]), 'C', __pyx_v_self->view.ndim)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 619, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; + __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(1, 623, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; goto __pyx_L0; - /* "View.MemoryView":615 + /* "View.MemoryView":619 * * * def is_c_contig(self): # <<<<<<<<<<<<<< @@ -8472,7 +8528,7 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_16 /* function exit code */ __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); __Pyx_AddTraceback("View.MemoryView.memoryview.is_c_contig", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; @@ -8481,7 +8537,7 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_16 return __pyx_r; } -/* "View.MemoryView":621 +/* "View.MemoryView":625 * return slice_is_contig(mslice[0], 'C', self.view.ndim) * * def is_f_contig(self): # <<<<<<<<<<<<<< @@ -8507,19 +8563,21 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_18 __Pyx_memviewslice __pyx_v_tmp; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; + __Pyx_memviewslice *__pyx_t_1; + PyObject *__pyx_t_2 = NULL; __Pyx_RefNannySetupContext("is_f_contig", 0); - /* "View.MemoryView":624 + /* "View.MemoryView":628 * 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_v_mslice = __pyx_memoryview_get_slice_from_memoryview(__pyx_v_self, (&__pyx_v_tmp)); + __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(1, 628, __pyx_L1_error) + __pyx_v_mslice = __pyx_t_1; - /* "View.MemoryView":625 + /* "View.MemoryView":629 * cdef __Pyx_memviewslice tmp * mslice = get_slice_from_memview(self, &tmp) * return slice_is_contig(mslice[0], 'F', self.view.ndim) # <<<<<<<<<<<<<< @@ -8527,13 +8585,13 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_18 * def copy(self): */ __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_memviewslice_is_contig((__pyx_v_mslice[0]), 'F', __pyx_v_self->view.ndim)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 625, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; + __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(1, 629, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L0; - /* "View.MemoryView":621 + /* "View.MemoryView":625 * return slice_is_contig(mslice[0], 'C', self.view.ndim) * * def is_f_contig(self): # <<<<<<<<<<<<<< @@ -8543,7 +8601,7 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_18 /* function exit code */ __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); __Pyx_AddTraceback("View.MemoryView.memoryview.is_f_contig", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; @@ -8552,7 +8610,7 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_18 return __pyx_r; } -/* "View.MemoryView":627 +/* "View.MemoryView":631 * return slice_is_contig(mslice[0], 'F', self.view.ndim) * * def copy(self): # <<<<<<<<<<<<<< @@ -8582,7 +8640,7 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_20 PyObject *__pyx_t_2 = NULL; __Pyx_RefNannySetupContext("copy", 0); - /* "View.MemoryView":629 + /* "View.MemoryView":633 * def copy(self): * cdef __Pyx_memviewslice mslice * cdef int flags = self.flags & ~PyBUF_F_CONTIGUOUS # <<<<<<<<<<<<<< @@ -8591,7 +8649,7 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_20 */ __pyx_v_flags = (__pyx_v_self->flags & (~PyBUF_F_CONTIGUOUS)); - /* "View.MemoryView":631 + /* "View.MemoryView":635 * cdef int flags = self.flags & ~PyBUF_F_CONTIGUOUS * * slice_copy(self, &mslice) # <<<<<<<<<<<<<< @@ -8600,17 +8658,17 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_20 */ __pyx_memoryview_slice_copy(__pyx_v_self, (&__pyx_v_mslice)); - /* "View.MemoryView":632 + /* "View.MemoryView":636 * * 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(1, 632, __pyx_L1_error) + __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(1, 636, __pyx_L1_error) __pyx_v_mslice = __pyx_t_1; - /* "View.MemoryView":637 + /* "View.MemoryView":641 * self.dtype_is_object) * * return memoryview_copy_from_slice(self, &mslice) # <<<<<<<<<<<<<< @@ -8618,13 +8676,13 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_20 * 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(1, 637, __pyx_L1_error) + __pyx_t_2 = __pyx_memoryview_copy_object_from_slice(__pyx_v_self, (&__pyx_v_mslice)); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 641, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __pyx_r = __pyx_t_2; __pyx_t_2 = 0; goto __pyx_L0; - /* "View.MemoryView":627 + /* "View.MemoryView":631 * return slice_is_contig(mslice[0], 'F', self.view.ndim) * * def copy(self): # <<<<<<<<<<<<<< @@ -8643,7 +8701,7 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_20 return __pyx_r; } -/* "View.MemoryView":639 +/* "View.MemoryView":643 * return memoryview_copy_from_slice(self, &mslice) * * def copy_fortran(self): # <<<<<<<<<<<<<< @@ -8674,7 +8732,7 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_22 PyObject *__pyx_t_2 = NULL; __Pyx_RefNannySetupContext("copy_fortran", 0); - /* "View.MemoryView":641 + /* "View.MemoryView":645 * def copy_fortran(self): * cdef __Pyx_memviewslice src, dst * cdef int flags = self.flags & ~PyBUF_C_CONTIGUOUS # <<<<<<<<<<<<<< @@ -8683,7 +8741,7 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_22 */ __pyx_v_flags = (__pyx_v_self->flags & (~PyBUF_C_CONTIGUOUS)); - /* "View.MemoryView":643 + /* "View.MemoryView":647 * cdef int flags = self.flags & ~PyBUF_C_CONTIGUOUS * * slice_copy(self, &src) # <<<<<<<<<<<<<< @@ -8692,17 +8750,17 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_22 */ __pyx_memoryview_slice_copy(__pyx_v_self, (&__pyx_v_src)); - /* "View.MemoryView":644 + /* "View.MemoryView":648 * * 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(1, 644, __pyx_L1_error) + __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(1, 648, __pyx_L1_error) __pyx_v_dst = __pyx_t_1; - /* "View.MemoryView":649 + /* "View.MemoryView":653 * self.dtype_is_object) * * return memoryview_copy_from_slice(self, &dst) # <<<<<<<<<<<<<< @@ -8710,13 +8768,13 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_22 * */ __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(1, 649, __pyx_L1_error) + __pyx_t_2 = __pyx_memoryview_copy_object_from_slice(__pyx_v_self, (&__pyx_v_dst)); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 653, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __pyx_r = __pyx_t_2; __pyx_t_2 = 0; goto __pyx_L0; - /* "View.MemoryView":639 + /* "View.MemoryView":643 * return memoryview_copy_from_slice(self, &mslice) * * def copy_fortran(self): # <<<<<<<<<<<<<< @@ -8842,7 +8900,7 @@ static PyObject *__pyx_pf___pyx_memoryview_2__setstate_cython__(CYTHON_UNUSED st return __pyx_r; } -/* "View.MemoryView":653 +/* "View.MemoryView":657 * * @cname('__pyx_memoryview_new') * cdef memoryview_cwrapper(object o, int flags, bint dtype_is_object, __Pyx_TypeInfo *typeinfo): # <<<<<<<<<<<<<< @@ -8859,18 +8917,18 @@ static PyObject *__pyx_memoryview_new(PyObject *__pyx_v_o, int __pyx_v_flags, in PyObject *__pyx_t_3 = NULL; __Pyx_RefNannySetupContext("memoryview_cwrapper", 0); - /* "View.MemoryView":654 + /* "View.MemoryView":658 * @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(1, 654, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_flags); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 658, __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(1, 654, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyBool_FromLong(__pyx_v_dtype_is_object); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 658, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 654, __pyx_L1_error) + __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 658, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_INCREF(__pyx_v_o); __Pyx_GIVEREF(__pyx_v_o); @@ -8881,13 +8939,13 @@ static PyObject *__pyx_memoryview_new(PyObject *__pyx_v_o, int __pyx_v_flags, in 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(1, 654, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_Call(((PyObject *)__pyx_memoryview_type), __pyx_t_3, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 658, __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":655 + /* "View.MemoryView":659 * 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 # <<<<<<<<<<<<<< @@ -8896,7 +8954,7 @@ static PyObject *__pyx_memoryview_new(PyObject *__pyx_v_o, int __pyx_v_flags, in */ __pyx_v_result->typeinfo = __pyx_v_typeinfo; - /* "View.MemoryView":656 + /* "View.MemoryView":660 * cdef memoryview result = memoryview(o, flags, dtype_is_object) * result.typeinfo = typeinfo * return result # <<<<<<<<<<<<<< @@ -8908,7 +8966,7 @@ static PyObject *__pyx_memoryview_new(PyObject *__pyx_v_o, int __pyx_v_flags, in __pyx_r = ((PyObject *)__pyx_v_result); goto __pyx_L0; - /* "View.MemoryView":653 + /* "View.MemoryView":657 * * @cname('__pyx_memoryview_new') * cdef memoryview_cwrapper(object o, int flags, bint dtype_is_object, __Pyx_TypeInfo *typeinfo): # <<<<<<<<<<<<<< @@ -8930,7 +8988,7 @@ static PyObject *__pyx_memoryview_new(PyObject *__pyx_v_o, int __pyx_v_flags, in return __pyx_r; } -/* "View.MemoryView":659 +/* "View.MemoryView":663 * * @cname('__pyx_memoryview_check') * cdef inline bint memoryview_check(object o): # <<<<<<<<<<<<<< @@ -8944,7 +9002,7 @@ static CYTHON_INLINE int __pyx_memoryview_check(PyObject *__pyx_v_o) { int __pyx_t_1; __Pyx_RefNannySetupContext("memoryview_check", 0); - /* "View.MemoryView":660 + /* "View.MemoryView":664 * @cname('__pyx_memoryview_check') * cdef inline bint memoryview_check(object o): * return isinstance(o, memoryview) # <<<<<<<<<<<<<< @@ -8955,7 +9013,7 @@ static CYTHON_INLINE int __pyx_memoryview_check(PyObject *__pyx_v_o) { __pyx_r = __pyx_t_1; goto __pyx_L0; - /* "View.MemoryView":659 + /* "View.MemoryView":663 * * @cname('__pyx_memoryview_check') * cdef inline bint memoryview_check(object o): # <<<<<<<<<<<<<< @@ -8969,7 +9027,7 @@ static CYTHON_INLINE int __pyx_memoryview_check(PyObject *__pyx_v_o) { return __pyx_r; } -/* "View.MemoryView":662 +/* "View.MemoryView":666 * return isinstance(o, memoryview) * * cdef tuple _unellipsify(object index, int ndim): # <<<<<<<<<<<<<< @@ -9000,7 +9058,7 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { PyObject *__pyx_t_11 = NULL; __Pyx_RefNannySetupContext("_unellipsify", 0); - /* "View.MemoryView":667 + /* "View.MemoryView":671 * full slices. * """ * if not isinstance(index, tuple): # <<<<<<<<<<<<<< @@ -9011,14 +9069,14 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { __pyx_t_2 = ((!(__pyx_t_1 != 0)) != 0); if (__pyx_t_2) { - /* "View.MemoryView":668 + /* "View.MemoryView":672 * """ * if not isinstance(index, tuple): * tup = (index,) # <<<<<<<<<<<<<< * else: * tup = index */ - __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 668, __pyx_L1_error) + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 672, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_INCREF(__pyx_v_index); __Pyx_GIVEREF(__pyx_v_index); @@ -9026,7 +9084,7 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { __pyx_v_tup = __pyx_t_3; __pyx_t_3 = 0; - /* "View.MemoryView":667 + /* "View.MemoryView":671 * full slices. * """ * if not isinstance(index, tuple): # <<<<<<<<<<<<<< @@ -9036,7 +9094,7 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { goto __pyx_L3; } - /* "View.MemoryView":670 + /* "View.MemoryView":674 * tup = (index,) * else: * tup = index # <<<<<<<<<<<<<< @@ -9049,19 +9107,19 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { } __pyx_L3:; - /* "View.MemoryView":672 + /* "View.MemoryView":676 * tup = index * * result = [] # <<<<<<<<<<<<<< * have_slices = False * seen_ellipsis = False */ - __pyx_t_3 = PyList_New(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 672, __pyx_L1_error) + __pyx_t_3 = PyList_New(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 676, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_v_result = ((PyObject*)__pyx_t_3); __pyx_t_3 = 0; - /* "View.MemoryView":673 + /* "View.MemoryView":677 * * result = [] * have_slices = False # <<<<<<<<<<<<<< @@ -9070,7 +9128,7 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { */ __pyx_v_have_slices = 0; - /* "View.MemoryView":674 + /* "View.MemoryView":678 * result = [] * have_slices = False * seen_ellipsis = False # <<<<<<<<<<<<<< @@ -9079,7 +9137,7 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { */ __pyx_v_seen_ellipsis = 0; - /* "View.MemoryView":675 + /* "View.MemoryView":679 * have_slices = False * seen_ellipsis = False * for idx, item in enumerate(tup): # <<<<<<<<<<<<<< @@ -9092,26 +9150,26 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { __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(1, 675, __pyx_L1_error) + __pyx_t_5 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_v_tup); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 679, __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(1, 675, __pyx_L1_error) + __pyx_t_6 = Py_TYPE(__pyx_t_4)->tp_iternext; if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 679, __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(1, 675, __pyx_L1_error) + __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(1, 679, __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(1, 675, __pyx_L1_error) + __pyx_t_7 = PySequence_ITEM(__pyx_t_4, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 679, __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(1, 675, __pyx_L1_error) + __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(1, 679, __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(1, 675, __pyx_L1_error) + __pyx_t_7 = PySequence_ITEM(__pyx_t_4, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 679, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_7); #endif } @@ -9121,7 +9179,7 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { PyObject* exc_type = PyErr_Occurred(); if (exc_type) { if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear(); - else __PYX_ERR(1, 675, __pyx_L1_error) + else __PYX_ERR(1, 679, __pyx_L1_error) } break; } @@ -9131,13 +9189,13 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { __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(1, 675, __pyx_L1_error) + __pyx_t_7 = __Pyx_PyInt_AddObjC(__pyx_t_3, __pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 679, __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":676 + /* "View.MemoryView":680 * seen_ellipsis = False * for idx, item in enumerate(tup): * if item is Ellipsis: # <<<<<<<<<<<<<< @@ -9148,7 +9206,7 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { __pyx_t_1 = (__pyx_t_2 != 0); if (__pyx_t_1) { - /* "View.MemoryView":677 + /* "View.MemoryView":681 * for idx, item in enumerate(tup): * if item is Ellipsis: * if not seen_ellipsis: # <<<<<<<<<<<<<< @@ -9158,15 +9216,15 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { __pyx_t_1 = ((!(__pyx_v_seen_ellipsis != 0)) != 0); if (__pyx_t_1) { - /* "View.MemoryView":678 + /* "View.MemoryView":682 * 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(1, 678, __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(1, 678, __pyx_L1_error) + __pyx_t_8 = PyObject_Length(__pyx_v_tup); if (unlikely(__pyx_t_8 == ((Py_ssize_t)-1))) __PYX_ERR(1, 682, __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(1, 682, __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++) { @@ -9175,10 +9233,10 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { PyList_SET_ITEM(__pyx_t_7, __pyx_temp, __pyx_slice__15); } } - __pyx_t_9 = __Pyx_PyList_Extend(__pyx_v_result, __pyx_t_7); if (unlikely(__pyx_t_9 == ((int)-1))) __PYX_ERR(1, 678, __pyx_L1_error) + __pyx_t_9 = __Pyx_PyList_Extend(__pyx_v_result, __pyx_t_7); if (unlikely(__pyx_t_9 == ((int)-1))) __PYX_ERR(1, 682, __pyx_L1_error) __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - /* "View.MemoryView":679 + /* "View.MemoryView":683 * if not seen_ellipsis: * result.extend([slice(None)] * (ndim - len(tup) + 1)) * seen_ellipsis = True # <<<<<<<<<<<<<< @@ -9187,7 +9245,7 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { */ __pyx_v_seen_ellipsis = 1; - /* "View.MemoryView":677 + /* "View.MemoryView":681 * for idx, item in enumerate(tup): * if item is Ellipsis: * if not seen_ellipsis: # <<<<<<<<<<<<<< @@ -9197,7 +9255,7 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { goto __pyx_L7; } - /* "View.MemoryView":681 + /* "View.MemoryView":685 * seen_ellipsis = True * else: * result.append(slice(None)) # <<<<<<<<<<<<<< @@ -9205,11 +9263,11 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { * else: */ /*else*/ { - __pyx_t_9 = __Pyx_PyList_Append(__pyx_v_result, __pyx_slice__15); if (unlikely(__pyx_t_9 == ((int)-1))) __PYX_ERR(1, 681, __pyx_L1_error) + __pyx_t_9 = __Pyx_PyList_Append(__pyx_v_result, __pyx_slice__15); if (unlikely(__pyx_t_9 == ((int)-1))) __PYX_ERR(1, 685, __pyx_L1_error) } __pyx_L7:; - /* "View.MemoryView":682 + /* "View.MemoryView":686 * else: * result.append(slice(None)) * have_slices = True # <<<<<<<<<<<<<< @@ -9218,7 +9276,7 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { */ __pyx_v_have_slices = 1; - /* "View.MemoryView":676 + /* "View.MemoryView":680 * seen_ellipsis = False * for idx, item in enumerate(tup): * if item is Ellipsis: # <<<<<<<<<<<<<< @@ -9228,7 +9286,7 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { goto __pyx_L6; } - /* "View.MemoryView":684 + /* "View.MemoryView":688 * have_slices = True * else: * if not isinstance(item, slice) and not PyIndex_Check(item): # <<<<<<<<<<<<<< @@ -9248,23 +9306,23 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { __pyx_L9_bool_binop_done:; if (unlikely(__pyx_t_1)) { - /* "View.MemoryView":685 + /* "View.MemoryView":689 * 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(1, 685, __pyx_L1_error) + __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(1, 689, __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(1, 685, __pyx_L1_error) + __pyx_t_11 = __Pyx_PyObject_CallOneArg(__pyx_builtin_TypeError, __pyx_t_7); if (unlikely(!__pyx_t_11)) __PYX_ERR(1, 689, __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(1, 685, __pyx_L1_error) + __PYX_ERR(1, 689, __pyx_L1_error) - /* "View.MemoryView":684 + /* "View.MemoryView":688 * have_slices = True * else: * if not isinstance(item, slice) and not PyIndex_Check(item): # <<<<<<<<<<<<<< @@ -9273,7 +9331,7 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { */ } - /* "View.MemoryView":687 + /* "View.MemoryView":691 * raise TypeError("Cannot index with type '%s'" % type(item)) * * have_slices = have_slices or isinstance(item, slice) # <<<<<<<<<<<<<< @@ -9292,18 +9350,18 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { __pyx_L11_bool_binop_done:; __pyx_v_have_slices = __pyx_t_1; - /* "View.MemoryView":688 + /* "View.MemoryView":692 * * 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(1, 688, __pyx_L1_error) + __pyx_t_9 = __Pyx_PyList_Append(__pyx_v_result, __pyx_v_item); if (unlikely(__pyx_t_9 == ((int)-1))) __PYX_ERR(1, 692, __pyx_L1_error) } __pyx_L6:; - /* "View.MemoryView":675 + /* "View.MemoryView":679 * have_slices = False * seen_ellipsis = False * for idx, item in enumerate(tup): # <<<<<<<<<<<<<< @@ -9314,17 +9372,17 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - /* "View.MemoryView":690 + /* "View.MemoryView":694 * 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(1, 690, __pyx_L1_error) + __pyx_t_5 = PyList_GET_SIZE(__pyx_v_result); if (unlikely(__pyx_t_5 == ((Py_ssize_t)-1))) __PYX_ERR(1, 694, __pyx_L1_error) __pyx_v_nslices = (__pyx_v_ndim - __pyx_t_5); - /* "View.MemoryView":691 + /* "View.MemoryView":695 * * nslices = ndim - len(result) * if nslices: # <<<<<<<<<<<<<< @@ -9334,14 +9392,14 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { __pyx_t_1 = (__pyx_v_nslices != 0); if (__pyx_t_1) { - /* "View.MemoryView":692 + /* "View.MemoryView":696 * 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(1, 692, __pyx_L1_error) + __pyx_t_3 = PyList_New(1 * ((__pyx_v_nslices<0) ? 0:__pyx_v_nslices)); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 696, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); { Py_ssize_t __pyx_temp; for (__pyx_temp=0; __pyx_temp < __pyx_v_nslices; __pyx_temp++) { @@ -9350,10 +9408,10 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { PyList_SET_ITEM(__pyx_t_3, __pyx_temp, __pyx_slice__15); } } - __pyx_t_9 = __Pyx_PyList_Extend(__pyx_v_result, __pyx_t_3); if (unlikely(__pyx_t_9 == ((int)-1))) __PYX_ERR(1, 692, __pyx_L1_error) + __pyx_t_9 = __Pyx_PyList_Extend(__pyx_v_result, __pyx_t_3); if (unlikely(__pyx_t_9 == ((int)-1))) __PYX_ERR(1, 696, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - /* "View.MemoryView":691 + /* "View.MemoryView":695 * * nslices = ndim - len(result) * if nslices: # <<<<<<<<<<<<<< @@ -9362,7 +9420,7 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { */ } - /* "View.MemoryView":694 + /* "View.MemoryView":698 * result.extend([slice(None)] * nslices) * * return have_slices or nslices, tuple(result) # <<<<<<<<<<<<<< @@ -9372,20 +9430,20 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_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(1, 694, __pyx_L1_error) + __pyx_t_4 = __Pyx_PyBool_FromLong(__pyx_v_have_slices); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 698, __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(1, 694, __pyx_L1_error) + __pyx_t_4 = PyInt_FromSsize_t(__pyx_v_nslices); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 698, __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(1, 694, __pyx_L1_error) + __pyx_t_4 = PyList_AsTuple(__pyx_v_result); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 698, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); - __pyx_t_11 = PyTuple_New(2); if (unlikely(!__pyx_t_11)) __PYX_ERR(1, 694, __pyx_L1_error) + __pyx_t_11 = PyTuple_New(2); if (unlikely(!__pyx_t_11)) __PYX_ERR(1, 698, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_11); __Pyx_GIVEREF(__pyx_t_3); PyTuple_SET_ITEM(__pyx_t_11, 0, __pyx_t_3); @@ -9397,7 +9455,7 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { __pyx_t_11 = 0; goto __pyx_L0; - /* "View.MemoryView":662 + /* "View.MemoryView":666 * return isinstance(o, memoryview) * * cdef tuple _unellipsify(object index, int ndim): # <<<<<<<<<<<<<< @@ -9423,7 +9481,7 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { return __pyx_r; } -/* "View.MemoryView":696 +/* "View.MemoryView":700 * return have_slices or nslices, tuple(result) * * cdef assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim): # <<<<<<<<<<<<<< @@ -9442,7 +9500,7 @@ static PyObject *assert_direct_dimensions(Py_ssize_t *__pyx_v_suboffsets, int __ PyObject *__pyx_t_5 = NULL; __Pyx_RefNannySetupContext("assert_direct_dimensions", 0); - /* "View.MemoryView":697 + /* "View.MemoryView":701 * * cdef assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim): * for suboffset in suboffsets[:ndim]: # <<<<<<<<<<<<<< @@ -9454,7 +9512,7 @@ static PyObject *assert_direct_dimensions(Py_ssize_t *__pyx_v_suboffsets, int __ __pyx_t_1 = __pyx_t_3; __pyx_v_suboffset = (__pyx_t_1[0]); - /* "View.MemoryView":698 + /* "View.MemoryView":702 * cdef assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim): * for suboffset in suboffsets[:ndim]: * if suboffset >= 0: # <<<<<<<<<<<<<< @@ -9464,20 +9522,20 @@ static PyObject *assert_direct_dimensions(Py_ssize_t *__pyx_v_suboffsets, int __ __pyx_t_4 = ((__pyx_v_suboffset >= 0) != 0); if (unlikely(__pyx_t_4)) { - /* "View.MemoryView":699 + /* "View.MemoryView":703 * 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__16, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 699, __pyx_L1_error) + __pyx_t_5 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__16, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 703, __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(1, 699, __pyx_L1_error) + __PYX_ERR(1, 703, __pyx_L1_error) - /* "View.MemoryView":698 + /* "View.MemoryView":702 * cdef assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim): * for suboffset in suboffsets[:ndim]: * if suboffset >= 0: # <<<<<<<<<<<<<< @@ -9487,7 +9545,7 @@ static PyObject *assert_direct_dimensions(Py_ssize_t *__pyx_v_suboffsets, int __ } } - /* "View.MemoryView":696 + /* "View.MemoryView":700 * return have_slices or nslices, tuple(result) * * cdef assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim): # <<<<<<<<<<<<<< @@ -9508,7 +9566,7 @@ static PyObject *assert_direct_dimensions(Py_ssize_t *__pyx_v_suboffsets, int __ return __pyx_r; } -/* "View.MemoryView":706 +/* "View.MemoryView":710 * * @cname('__pyx_memview_slice') * cdef memoryview memview_slice(memoryview memview, object indices): # <<<<<<<<<<<<<< @@ -9549,7 +9607,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ Py_ssize_t __pyx_t_12; __Pyx_RefNannySetupContext("memview_slice", 0); - /* "View.MemoryView":707 + /* "View.MemoryView":711 * @cname('__pyx_memview_slice') * cdef memoryview memview_slice(memoryview memview, object indices): * cdef int new_ndim = 0, suboffset_dim = -1, dim # <<<<<<<<<<<<<< @@ -9559,7 +9617,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ __pyx_v_new_ndim = 0; __pyx_v_suboffset_dim = -1; - /* "View.MemoryView":714 + /* "View.MemoryView":718 * * * memset(&dst, 0, sizeof(dst)) # <<<<<<<<<<<<<< @@ -9568,7 +9626,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ */ (void)(memset((&__pyx_v_dst), 0, (sizeof(__pyx_v_dst)))); - /* "View.MemoryView":718 + /* "View.MemoryView":722 * cdef _memoryviewslice memviewsliceobj * * assert memview.view.ndim > 0 # <<<<<<<<<<<<<< @@ -9579,12 +9637,12 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ if (unlikely(!Py_OptimizeFlag)) { if (unlikely(!((__pyx_v_memview->view.ndim > 0) != 0))) { PyErr_SetNone(PyExc_AssertionError); - __PYX_ERR(1, 718, __pyx_L1_error) + __PYX_ERR(1, 722, __pyx_L1_error) } } #endif - /* "View.MemoryView":720 + /* "View.MemoryView":724 * assert memview.view.ndim > 0 * * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< @@ -9595,20 +9653,20 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ __pyx_t_2 = (__pyx_t_1 != 0); if (__pyx_t_2) { - /* "View.MemoryView":721 + /* "View.MemoryView":725 * * 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(1, 721, __pyx_L1_error) + if (!(likely(((((PyObject *)__pyx_v_memview)) == Py_None) || likely(__Pyx_TypeTest(((PyObject *)__pyx_v_memview), __pyx_memoryviewslice_type))))) __PYX_ERR(1, 725, __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":722 + /* "View.MemoryView":726 * if isinstance(memview, _memoryviewslice): * memviewsliceobj = memview * p_src = &memviewsliceobj.from_slice # <<<<<<<<<<<<<< @@ -9617,7 +9675,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ */ __pyx_v_p_src = (&__pyx_v_memviewsliceobj->from_slice); - /* "View.MemoryView":720 + /* "View.MemoryView":724 * assert memview.view.ndim > 0 * * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< @@ -9627,7 +9685,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ goto __pyx_L3; } - /* "View.MemoryView":724 + /* "View.MemoryView":728 * p_src = &memviewsliceobj.from_slice * else: * slice_copy(memview, &src) # <<<<<<<<<<<<<< @@ -9637,7 +9695,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ /*else*/ { __pyx_memoryview_slice_copy(__pyx_v_memview, (&__pyx_v_src)); - /* "View.MemoryView":725 + /* "View.MemoryView":729 * else: * slice_copy(memview, &src) * p_src = &src # <<<<<<<<<<<<<< @@ -9648,7 +9706,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ } __pyx_L3:; - /* "View.MemoryView":731 + /* "View.MemoryView":735 * * * dst.memview = p_src.memview # <<<<<<<<<<<<<< @@ -9658,7 +9716,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ __pyx_t_4 = __pyx_v_p_src->memview; __pyx_v_dst.memview = __pyx_t_4; - /* "View.MemoryView":732 + /* "View.MemoryView":736 * * dst.memview = p_src.memview * dst.data = p_src.data # <<<<<<<<<<<<<< @@ -9668,7 +9726,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ __pyx_t_5 = __pyx_v_p_src->data; __pyx_v_dst.data = __pyx_t_5; - /* "View.MemoryView":737 + /* "View.MemoryView":741 * * * cdef __Pyx_memviewslice *p_dst = &dst # <<<<<<<<<<<<<< @@ -9677,7 +9735,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ */ __pyx_v_p_dst = (&__pyx_v_dst); - /* "View.MemoryView":738 + /* "View.MemoryView":742 * * cdef __Pyx_memviewslice *p_dst = &dst * cdef int *p_suboffset_dim = &suboffset_dim # <<<<<<<<<<<<<< @@ -9686,7 +9744,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ */ __pyx_v_p_suboffset_dim = (&__pyx_v_suboffset_dim); - /* "View.MemoryView":742 + /* "View.MemoryView":746 * cdef bint have_start, have_stop, have_step * * for dim, index in enumerate(indices): # <<<<<<<<<<<<<< @@ -9698,26 +9756,26 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ __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(1, 742, __pyx_L1_error) + __pyx_t_7 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_v_indices); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 746, __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(1, 742, __pyx_L1_error) + __pyx_t_8 = Py_TYPE(__pyx_t_3)->tp_iternext; if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 746, __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(1, 742, __pyx_L1_error) + __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(1, 746, __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(1, 742, __pyx_L1_error) + __pyx_t_9 = PySequence_ITEM(__pyx_t_3, __pyx_t_7); __pyx_t_7++; if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 746, __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(1, 742, __pyx_L1_error) + __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(1, 746, __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(1, 742, __pyx_L1_error) + __pyx_t_9 = PySequence_ITEM(__pyx_t_3, __pyx_t_7); __pyx_t_7++; if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 746, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_9); #endif } @@ -9727,7 +9785,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ PyObject* exc_type = PyErr_Occurred(); if (exc_type) { if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear(); - else __PYX_ERR(1, 742, __pyx_L1_error) + else __PYX_ERR(1, 746, __pyx_L1_error) } break; } @@ -9738,7 +9796,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ __pyx_v_dim = __pyx_t_6; __pyx_t_6 = (__pyx_t_6 + 1); - /* "View.MemoryView":743 + /* "View.MemoryView":747 * * for dim, index in enumerate(indices): * if PyIndex_Check(index): # <<<<<<<<<<<<<< @@ -9748,25 +9806,25 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ __pyx_t_2 = (PyIndex_Check(__pyx_v_index) != 0); if (__pyx_t_2) { - /* "View.MemoryView":747 + /* "View.MemoryView":751 * 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(1, 747, __pyx_L1_error) + __pyx_t_10 = __Pyx_PyIndex_AsSsize_t(__pyx_v_index); if (unlikely((__pyx_t_10 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(1, 751, __pyx_L1_error) - /* "View.MemoryView":744 + /* "View.MemoryView":748 * 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(1, 744, __pyx_L1_error) + __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(1, 748, __pyx_L1_error) - /* "View.MemoryView":743 + /* "View.MemoryView":747 * * for dim, index in enumerate(indices): * if PyIndex_Check(index): # <<<<<<<<<<<<<< @@ -9776,7 +9834,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ goto __pyx_L6; } - /* "View.MemoryView":750 + /* "View.MemoryView":754 * 0, 0, 0, # have_{start,stop,step} * False) * elif index is None: # <<<<<<<<<<<<<< @@ -9787,7 +9845,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ __pyx_t_1 = (__pyx_t_2 != 0); if (__pyx_t_1) { - /* "View.MemoryView":751 + /* "View.MemoryView":755 * False) * elif index is None: * p_dst.shape[new_ndim] = 1 # <<<<<<<<<<<<<< @@ -9796,7 +9854,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ */ (__pyx_v_p_dst->shape[__pyx_v_new_ndim]) = 1; - /* "View.MemoryView":752 + /* "View.MemoryView":756 * elif index is None: * p_dst.shape[new_ndim] = 1 * p_dst.strides[new_ndim] = 0 # <<<<<<<<<<<<<< @@ -9805,7 +9863,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ */ (__pyx_v_p_dst->strides[__pyx_v_new_ndim]) = 0; - /* "View.MemoryView":753 + /* "View.MemoryView":757 * p_dst.shape[new_ndim] = 1 * p_dst.strides[new_ndim] = 0 * p_dst.suboffsets[new_ndim] = -1 # <<<<<<<<<<<<<< @@ -9814,7 +9872,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ */ (__pyx_v_p_dst->suboffsets[__pyx_v_new_ndim]) = -1L; - /* "View.MemoryView":754 + /* "View.MemoryView":758 * p_dst.strides[new_ndim] = 0 * p_dst.suboffsets[new_ndim] = -1 * new_ndim += 1 # <<<<<<<<<<<<<< @@ -9823,7 +9881,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ */ __pyx_v_new_ndim = (__pyx_v_new_ndim + 1); - /* "View.MemoryView":750 + /* "View.MemoryView":754 * 0, 0, 0, # have_{start,stop,step} * False) * elif index is None: # <<<<<<<<<<<<<< @@ -9833,7 +9891,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ goto __pyx_L6; } - /* "View.MemoryView":756 + /* "View.MemoryView":760 * new_ndim += 1 * else: * start = index.start or 0 # <<<<<<<<<<<<<< @@ -9841,13 +9899,13 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ * 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(1, 756, __pyx_L1_error) + __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_v_index, __pyx_n_s_start); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 760, __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(1, 756, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_9); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(1, 760, __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(1, 756, __pyx_L1_error) + __pyx_t_12 = __Pyx_PyIndex_AsSsize_t(__pyx_t_9); if (unlikely((__pyx_t_12 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(1, 760, __pyx_L1_error) __pyx_t_10 = __pyx_t_12; __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; goto __pyx_L7_bool_binop_done; @@ -9856,20 +9914,20 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ __pyx_L7_bool_binop_done:; __pyx_v_start = __pyx_t_10; - /* "View.MemoryView":757 + /* "View.MemoryView":761 * 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(1, 757, __pyx_L1_error) + __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_v_index, __pyx_n_s_stop); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 761, __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(1, 757, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_9); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(1, 761, __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(1, 757, __pyx_L1_error) + __pyx_t_12 = __Pyx_PyIndex_AsSsize_t(__pyx_t_9); if (unlikely((__pyx_t_12 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(1, 761, __pyx_L1_error) __pyx_t_10 = __pyx_t_12; __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; goto __pyx_L9_bool_binop_done; @@ -9878,20 +9936,20 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ __pyx_L9_bool_binop_done:; __pyx_v_stop = __pyx_t_10; - /* "View.MemoryView":758 + /* "View.MemoryView":762 * 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(1, 758, __pyx_L1_error) + __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_v_index, __pyx_n_s_step); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 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(1, 758, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_9); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(1, 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(1, 758, __pyx_L1_error) + __pyx_t_12 = __Pyx_PyIndex_AsSsize_t(__pyx_t_9); if (unlikely((__pyx_t_12 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(1, 762, __pyx_L1_error) __pyx_t_10 = __pyx_t_12; __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; goto __pyx_L11_bool_binop_done; @@ -9900,55 +9958,55 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ __pyx_L11_bool_binop_done:; __pyx_v_step = __pyx_t_10; - /* "View.MemoryView":760 + /* "View.MemoryView":764 * 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(1, 760, __pyx_L1_error) + __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_v_index, __pyx_n_s_start); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 764, __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":761 + /* "View.MemoryView":765 * * 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(1, 761, __pyx_L1_error) + __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_v_index, __pyx_n_s_stop); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 765, __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":762 + /* "View.MemoryView":766 * 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(1, 762, __pyx_L1_error) + __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_v_index, __pyx_n_s_step); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 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_step = __pyx_t_1; - /* "View.MemoryView":764 + /* "View.MemoryView":768 * 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(1, 764, __pyx_L1_error) + __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(1, 768, __pyx_L1_error) - /* "View.MemoryView":770 + /* "View.MemoryView":774 * have_start, have_stop, have_step, * True) * new_ndim += 1 # <<<<<<<<<<<<<< @@ -9959,7 +10017,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ } __pyx_L6:; - /* "View.MemoryView":742 + /* "View.MemoryView":746 * cdef bint have_start, have_stop, have_step * * for dim, index in enumerate(indices): # <<<<<<<<<<<<<< @@ -9969,7 +10027,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ } __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - /* "View.MemoryView":772 + /* "View.MemoryView":776 * new_ndim += 1 * * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< @@ -9980,7 +10038,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ __pyx_t_2 = (__pyx_t_1 != 0); if (__pyx_t_2) { - /* "View.MemoryView":773 + /* "View.MemoryView":777 * * if isinstance(memview, _memoryviewslice): * return memoryview_fromslice(dst, new_ndim, # <<<<<<<<<<<<<< @@ -9989,39 +10047,39 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ */ __Pyx_XDECREF(((PyObject *)__pyx_r)); - /* "View.MemoryView":774 + /* "View.MemoryView":778 * 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(1, 774, __pyx_L1_error) } + if (unlikely(!__pyx_v_memviewsliceobj)) { __Pyx_RaiseUnboundLocalError("memviewsliceobj"); __PYX_ERR(1, 778, __pyx_L1_error) } - /* "View.MemoryView":775 + /* "View.MemoryView":779 * 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(1, 775, __pyx_L1_error) } + if (unlikely(!__pyx_v_memviewsliceobj)) { __Pyx_RaiseUnboundLocalError("memviewsliceobj"); __PYX_ERR(1, 779, __pyx_L1_error) } - /* "View.MemoryView":773 + /* "View.MemoryView":777 * * 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(1, 773, __pyx_L1_error) + __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(1, 777, __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(1, 773, __pyx_L1_error) + if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_memoryview_type))))) __PYX_ERR(1, 777, __pyx_L1_error) __pyx_r = ((struct __pyx_memoryview_obj *)__pyx_t_3); __pyx_t_3 = 0; goto __pyx_L0; - /* "View.MemoryView":772 + /* "View.MemoryView":776 * new_ndim += 1 * * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< @@ -10030,7 +10088,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ */ } - /* "View.MemoryView":778 + /* "View.MemoryView":782 * memview.dtype_is_object) * else: * return memoryview_fromslice(dst, new_ndim, NULL, NULL, # <<<<<<<<<<<<<< @@ -10040,30 +10098,30 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ /*else*/ { __Pyx_XDECREF(((PyObject *)__pyx_r)); - /* "View.MemoryView":779 + /* "View.MemoryView":783 * 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(1, 778, __pyx_L1_error) + __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(1, 782, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); - /* "View.MemoryView":778 + /* "View.MemoryView":782 * 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(1, 778, __pyx_L1_error) + if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_memoryview_type))))) __PYX_ERR(1, 782, __pyx_L1_error) __pyx_r = ((struct __pyx_memoryview_obj *)__pyx_t_3); __pyx_t_3 = 0; goto __pyx_L0; } - /* "View.MemoryView":706 + /* "View.MemoryView":710 * * @cname('__pyx_memview_slice') * cdef memoryview memview_slice(memoryview memview, object indices): # <<<<<<<<<<<<<< @@ -10085,7 +10143,7 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_ return __pyx_r; } -/* "View.MemoryView":803 +/* "View.MemoryView":807 * * @cname('__pyx_memoryview_slice_memviewslice') * cdef int slice_memviewslice( # <<<<<<<<<<<<<< @@ -10101,7 +10159,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, int __pyx_t_2; int __pyx_t_3; - /* "View.MemoryView":823 + /* "View.MemoryView":827 * cdef bint negative_step * * if not is_slice: # <<<<<<<<<<<<<< @@ -10111,7 +10169,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_t_1 = ((!(__pyx_v_is_slice != 0)) != 0); if (__pyx_t_1) { - /* "View.MemoryView":825 + /* "View.MemoryView":829 * if not is_slice: * * if start < 0: # <<<<<<<<<<<<<< @@ -10121,7 +10179,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_t_1 = ((__pyx_v_start < 0) != 0); if (__pyx_t_1) { - /* "View.MemoryView":826 + /* "View.MemoryView":830 * * if start < 0: * start += shape # <<<<<<<<<<<<<< @@ -10130,7 +10188,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ __pyx_v_start = (__pyx_v_start + __pyx_v_shape); - /* "View.MemoryView":825 + /* "View.MemoryView":829 * if not is_slice: * * if start < 0: # <<<<<<<<<<<<<< @@ -10139,7 +10197,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ } - /* "View.MemoryView":827 + /* "View.MemoryView":831 * if start < 0: * start += shape * if not 0 <= start < shape: # <<<<<<<<<<<<<< @@ -10153,16 +10211,16 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_t_2 = ((!(__pyx_t_1 != 0)) != 0); if (__pyx_t_2) { - /* "View.MemoryView":828 + /* "View.MemoryView":832 * 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(1, 828, __pyx_L1_error) + __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(1, 832, __pyx_L1_error) - /* "View.MemoryView":827 + /* "View.MemoryView":831 * if start < 0: * start += shape * if not 0 <= start < shape: # <<<<<<<<<<<<<< @@ -10171,7 +10229,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ } - /* "View.MemoryView":823 + /* "View.MemoryView":827 * cdef bint negative_step * * if not is_slice: # <<<<<<<<<<<<<< @@ -10181,7 +10239,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, goto __pyx_L3; } - /* "View.MemoryView":831 + /* "View.MemoryView":835 * else: * * negative_step = have_step != 0 and step < 0 # <<<<<<<<<<<<<< @@ -10200,7 +10258,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_L6_bool_binop_done:; __pyx_v_negative_step = __pyx_t_2; - /* "View.MemoryView":833 + /* "View.MemoryView":837 * negative_step = have_step != 0 and step < 0 * * if have_step and step == 0: # <<<<<<<<<<<<<< @@ -10218,16 +10276,16 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_L9_bool_binop_done:; if (__pyx_t_2) { - /* "View.MemoryView":834 + /* "View.MemoryView":838 * * 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(1, 834, __pyx_L1_error) + __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(1, 838, __pyx_L1_error) - /* "View.MemoryView":833 + /* "View.MemoryView":837 * negative_step = have_step != 0 and step < 0 * * if have_step and step == 0: # <<<<<<<<<<<<<< @@ -10236,7 +10294,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ } - /* "View.MemoryView":837 + /* "View.MemoryView":841 * * * if have_start: # <<<<<<<<<<<<<< @@ -10246,7 +10304,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_t_2 = (__pyx_v_have_start != 0); if (__pyx_t_2) { - /* "View.MemoryView":838 + /* "View.MemoryView":842 * * if have_start: * if start < 0: # <<<<<<<<<<<<<< @@ -10256,7 +10314,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_t_2 = ((__pyx_v_start < 0) != 0); if (__pyx_t_2) { - /* "View.MemoryView":839 + /* "View.MemoryView":843 * if have_start: * if start < 0: * start += shape # <<<<<<<<<<<<<< @@ -10265,7 +10323,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ __pyx_v_start = (__pyx_v_start + __pyx_v_shape); - /* "View.MemoryView":840 + /* "View.MemoryView":844 * if start < 0: * start += shape * if start < 0: # <<<<<<<<<<<<<< @@ -10275,7 +10333,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_t_2 = ((__pyx_v_start < 0) != 0); if (__pyx_t_2) { - /* "View.MemoryView":841 + /* "View.MemoryView":845 * start += shape * if start < 0: * start = 0 # <<<<<<<<<<<<<< @@ -10284,7 +10342,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ __pyx_v_start = 0; - /* "View.MemoryView":840 + /* "View.MemoryView":844 * if start < 0: * start += shape * if start < 0: # <<<<<<<<<<<<<< @@ -10293,7 +10351,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ } - /* "View.MemoryView":838 + /* "View.MemoryView":842 * * if have_start: * if start < 0: # <<<<<<<<<<<<<< @@ -10303,7 +10361,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, goto __pyx_L12; } - /* "View.MemoryView":842 + /* "View.MemoryView":846 * if start < 0: * start = 0 * elif start >= shape: # <<<<<<<<<<<<<< @@ -10313,7 +10371,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_t_2 = ((__pyx_v_start >= __pyx_v_shape) != 0); if (__pyx_t_2) { - /* "View.MemoryView":843 + /* "View.MemoryView":847 * start = 0 * elif start >= shape: * if negative_step: # <<<<<<<<<<<<<< @@ -10323,7 +10381,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_t_2 = (__pyx_v_negative_step != 0); if (__pyx_t_2) { - /* "View.MemoryView":844 + /* "View.MemoryView":848 * elif start >= shape: * if negative_step: * start = shape - 1 # <<<<<<<<<<<<<< @@ -10332,7 +10390,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ __pyx_v_start = (__pyx_v_shape - 1); - /* "View.MemoryView":843 + /* "View.MemoryView":847 * start = 0 * elif start >= shape: * if negative_step: # <<<<<<<<<<<<<< @@ -10342,7 +10400,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, goto __pyx_L14; } - /* "View.MemoryView":846 + /* "View.MemoryView":850 * start = shape - 1 * else: * start = shape # <<<<<<<<<<<<<< @@ -10354,7 +10412,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, } __pyx_L14:; - /* "View.MemoryView":842 + /* "View.MemoryView":846 * if start < 0: * start = 0 * elif start >= shape: # <<<<<<<<<<<<<< @@ -10364,7 +10422,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, } __pyx_L12:; - /* "View.MemoryView":837 + /* "View.MemoryView":841 * * * if have_start: # <<<<<<<<<<<<<< @@ -10374,7 +10432,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, goto __pyx_L11; } - /* "View.MemoryView":848 + /* "View.MemoryView":852 * start = shape * else: * if negative_step: # <<<<<<<<<<<<<< @@ -10385,7 +10443,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_t_2 = (__pyx_v_negative_step != 0); if (__pyx_t_2) { - /* "View.MemoryView":849 + /* "View.MemoryView":853 * else: * if negative_step: * start = shape - 1 # <<<<<<<<<<<<<< @@ -10394,7 +10452,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ __pyx_v_start = (__pyx_v_shape - 1); - /* "View.MemoryView":848 + /* "View.MemoryView":852 * start = shape * else: * if negative_step: # <<<<<<<<<<<<<< @@ -10404,7 +10462,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, goto __pyx_L15; } - /* "View.MemoryView":851 + /* "View.MemoryView":855 * start = shape - 1 * else: * start = 0 # <<<<<<<<<<<<<< @@ -10418,7 +10476,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, } __pyx_L11:; - /* "View.MemoryView":853 + /* "View.MemoryView":857 * start = 0 * * if have_stop: # <<<<<<<<<<<<<< @@ -10428,7 +10486,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_t_2 = (__pyx_v_have_stop != 0); if (__pyx_t_2) { - /* "View.MemoryView":854 + /* "View.MemoryView":858 * * if have_stop: * if stop < 0: # <<<<<<<<<<<<<< @@ -10438,7 +10496,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_t_2 = ((__pyx_v_stop < 0) != 0); if (__pyx_t_2) { - /* "View.MemoryView":855 + /* "View.MemoryView":859 * if have_stop: * if stop < 0: * stop += shape # <<<<<<<<<<<<<< @@ -10447,7 +10505,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ __pyx_v_stop = (__pyx_v_stop + __pyx_v_shape); - /* "View.MemoryView":856 + /* "View.MemoryView":860 * if stop < 0: * stop += shape * if stop < 0: # <<<<<<<<<<<<<< @@ -10457,7 +10515,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_t_2 = ((__pyx_v_stop < 0) != 0); if (__pyx_t_2) { - /* "View.MemoryView":857 + /* "View.MemoryView":861 * stop += shape * if stop < 0: * stop = 0 # <<<<<<<<<<<<<< @@ -10466,7 +10524,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ __pyx_v_stop = 0; - /* "View.MemoryView":856 + /* "View.MemoryView":860 * if stop < 0: * stop += shape * if stop < 0: # <<<<<<<<<<<<<< @@ -10475,7 +10533,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ } - /* "View.MemoryView":854 + /* "View.MemoryView":858 * * if have_stop: * if stop < 0: # <<<<<<<<<<<<<< @@ -10485,7 +10543,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, goto __pyx_L17; } - /* "View.MemoryView":858 + /* "View.MemoryView":862 * if stop < 0: * stop = 0 * elif stop > shape: # <<<<<<<<<<<<<< @@ -10495,7 +10553,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_t_2 = ((__pyx_v_stop > __pyx_v_shape) != 0); if (__pyx_t_2) { - /* "View.MemoryView":859 + /* "View.MemoryView":863 * stop = 0 * elif stop > shape: * stop = shape # <<<<<<<<<<<<<< @@ -10504,7 +10562,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ __pyx_v_stop = __pyx_v_shape; - /* "View.MemoryView":858 + /* "View.MemoryView":862 * if stop < 0: * stop = 0 * elif stop > shape: # <<<<<<<<<<<<<< @@ -10514,7 +10572,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, } __pyx_L17:; - /* "View.MemoryView":853 + /* "View.MemoryView":857 * start = 0 * * if have_stop: # <<<<<<<<<<<<<< @@ -10524,7 +10582,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, goto __pyx_L16; } - /* "View.MemoryView":861 + /* "View.MemoryView":865 * stop = shape * else: * if negative_step: # <<<<<<<<<<<<<< @@ -10535,7 +10593,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_t_2 = (__pyx_v_negative_step != 0); if (__pyx_t_2) { - /* "View.MemoryView":862 + /* "View.MemoryView":866 * else: * if negative_step: * stop = -1 # <<<<<<<<<<<<<< @@ -10544,7 +10602,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ __pyx_v_stop = -1L; - /* "View.MemoryView":861 + /* "View.MemoryView":865 * stop = shape * else: * if negative_step: # <<<<<<<<<<<<<< @@ -10554,7 +10612,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, goto __pyx_L19; } - /* "View.MemoryView":864 + /* "View.MemoryView":868 * stop = -1 * else: * stop = shape # <<<<<<<<<<<<<< @@ -10568,7 +10626,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, } __pyx_L16:; - /* "View.MemoryView":866 + /* "View.MemoryView":870 * stop = shape * * if not have_step: # <<<<<<<<<<<<<< @@ -10578,7 +10636,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_t_2 = ((!(__pyx_v_have_step != 0)) != 0); if (__pyx_t_2) { - /* "View.MemoryView":867 + /* "View.MemoryView":871 * * if not have_step: * step = 1 # <<<<<<<<<<<<<< @@ -10587,7 +10645,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ __pyx_v_step = 1; - /* "View.MemoryView":866 + /* "View.MemoryView":870 * stop = shape * * if not have_step: # <<<<<<<<<<<<<< @@ -10596,7 +10654,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ } - /* "View.MemoryView":871 + /* "View.MemoryView":875 * * with cython.cdivision(True): * new_shape = (stop - start) // step # <<<<<<<<<<<<<< @@ -10605,7 +10663,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ __pyx_v_new_shape = ((__pyx_v_stop - __pyx_v_start) / __pyx_v_step); - /* "View.MemoryView":873 + /* "View.MemoryView":877 * new_shape = (stop - start) // step * * if (stop - start) - step * new_shape: # <<<<<<<<<<<<<< @@ -10615,7 +10673,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_t_2 = (((__pyx_v_stop - __pyx_v_start) - (__pyx_v_step * __pyx_v_new_shape)) != 0); if (__pyx_t_2) { - /* "View.MemoryView":874 + /* "View.MemoryView":878 * * if (stop - start) - step * new_shape: * new_shape += 1 # <<<<<<<<<<<<<< @@ -10624,7 +10682,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ __pyx_v_new_shape = (__pyx_v_new_shape + 1); - /* "View.MemoryView":873 + /* "View.MemoryView":877 * new_shape = (stop - start) // step * * if (stop - start) - step * new_shape: # <<<<<<<<<<<<<< @@ -10633,7 +10691,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ } - /* "View.MemoryView":876 + /* "View.MemoryView":880 * new_shape += 1 * * if new_shape < 0: # <<<<<<<<<<<<<< @@ -10643,7 +10701,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_t_2 = ((__pyx_v_new_shape < 0) != 0); if (__pyx_t_2) { - /* "View.MemoryView":877 + /* "View.MemoryView":881 * * if new_shape < 0: * new_shape = 0 # <<<<<<<<<<<<<< @@ -10652,7 +10710,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ __pyx_v_new_shape = 0; - /* "View.MemoryView":876 + /* "View.MemoryView":880 * new_shape += 1 * * if new_shape < 0: # <<<<<<<<<<<<<< @@ -10661,7 +10719,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ } - /* "View.MemoryView":880 + /* "View.MemoryView":884 * * * dst.strides[new_ndim] = stride * step # <<<<<<<<<<<<<< @@ -10670,7 +10728,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ (__pyx_v_dst->strides[__pyx_v_new_ndim]) = (__pyx_v_stride * __pyx_v_step); - /* "View.MemoryView":881 + /* "View.MemoryView":885 * * dst.strides[new_ndim] = stride * step * dst.shape[new_ndim] = new_shape # <<<<<<<<<<<<<< @@ -10679,7 +10737,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ (__pyx_v_dst->shape[__pyx_v_new_ndim]) = __pyx_v_new_shape; - /* "View.MemoryView":882 + /* "View.MemoryView":886 * dst.strides[new_ndim] = stride * step * dst.shape[new_ndim] = new_shape * dst.suboffsets[new_ndim] = suboffset # <<<<<<<<<<<<<< @@ -10690,7 +10748,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, } __pyx_L3:; - /* "View.MemoryView":885 + /* "View.MemoryView":889 * * * if suboffset_dim[0] < 0: # <<<<<<<<<<<<<< @@ -10700,7 +10758,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_t_2 = (((__pyx_v_suboffset_dim[0]) < 0) != 0); if (__pyx_t_2) { - /* "View.MemoryView":886 + /* "View.MemoryView":890 * * if suboffset_dim[0] < 0: * dst.data += start * stride # <<<<<<<<<<<<<< @@ -10709,7 +10767,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ __pyx_v_dst->data = (__pyx_v_dst->data + (__pyx_v_start * __pyx_v_stride)); - /* "View.MemoryView":885 + /* "View.MemoryView":889 * * * if suboffset_dim[0] < 0: # <<<<<<<<<<<<<< @@ -10719,7 +10777,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, goto __pyx_L23; } - /* "View.MemoryView":888 + /* "View.MemoryView":892 * dst.data += start * stride * else: * dst.suboffsets[suboffset_dim[0]] += start * stride # <<<<<<<<<<<<<< @@ -10732,7 +10790,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, } __pyx_L23:; - /* "View.MemoryView":890 + /* "View.MemoryView":894 * dst.suboffsets[suboffset_dim[0]] += start * stride * * if suboffset >= 0: # <<<<<<<<<<<<<< @@ -10742,7 +10800,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_t_2 = ((__pyx_v_suboffset >= 0) != 0); if (__pyx_t_2) { - /* "View.MemoryView":891 + /* "View.MemoryView":895 * * if suboffset >= 0: * if not is_slice: # <<<<<<<<<<<<<< @@ -10752,7 +10810,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_t_2 = ((!(__pyx_v_is_slice != 0)) != 0); if (__pyx_t_2) { - /* "View.MemoryView":892 + /* "View.MemoryView":896 * if suboffset >= 0: * if not is_slice: * if new_ndim == 0: # <<<<<<<<<<<<<< @@ -10762,7 +10820,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_t_2 = ((__pyx_v_new_ndim == 0) != 0); if (__pyx_t_2) { - /* "View.MemoryView":893 + /* "View.MemoryView":897 * if not is_slice: * if new_ndim == 0: * dst.data = ( dst.data)[0] + suboffset # <<<<<<<<<<<<<< @@ -10771,7 +10829,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ __pyx_v_dst->data = ((((char **)__pyx_v_dst->data)[0]) + __pyx_v_suboffset); - /* "View.MemoryView":892 + /* "View.MemoryView":896 * if suboffset >= 0: * if not is_slice: * if new_ndim == 0: # <<<<<<<<<<<<<< @@ -10781,7 +10839,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, goto __pyx_L26; } - /* "View.MemoryView":895 + /* "View.MemoryView":899 * dst.data = ( dst.data)[0] + suboffset * else: * _err_dim(IndexError, "All dimensions preceding dimension %d " # <<<<<<<<<<<<<< @@ -10790,18 +10848,18 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ /*else*/ { - /* "View.MemoryView":896 + /* "View.MemoryView":900 * 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(1, 895, __pyx_L1_error) + __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(1, 899, __pyx_L1_error) } __pyx_L26:; - /* "View.MemoryView":891 + /* "View.MemoryView":895 * * if suboffset >= 0: * if not is_slice: # <<<<<<<<<<<<<< @@ -10811,7 +10869,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, goto __pyx_L25; } - /* "View.MemoryView":898 + /* "View.MemoryView":902 * "must be indexed and not sliced", dim) * else: * suboffset_dim[0] = new_ndim # <<<<<<<<<<<<<< @@ -10823,7 +10881,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, } __pyx_L25:; - /* "View.MemoryView":890 + /* "View.MemoryView":894 * dst.suboffsets[suboffset_dim[0]] += start * stride * * if suboffset >= 0: # <<<<<<<<<<<<<< @@ -10832,7 +10890,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, */ } - /* "View.MemoryView":900 + /* "View.MemoryView":904 * suboffset_dim[0] = new_ndim * * return 0 # <<<<<<<<<<<<<< @@ -10842,7 +10900,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, __pyx_r = 0; goto __pyx_L0; - /* "View.MemoryView":803 + /* "View.MemoryView":807 * * @cname('__pyx_memoryview_slice_memviewslice') * cdef int slice_memviewslice( # <<<<<<<<<<<<<< @@ -10866,7 +10924,7 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, return __pyx_r; } -/* "View.MemoryView":906 +/* "View.MemoryView":910 * * @cname('__pyx_pybuffer_index') * cdef char *pybuffer_index(Py_buffer *view, char *bufp, Py_ssize_t index, # <<<<<<<<<<<<<< @@ -10888,7 +10946,7 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P PyObject *__pyx_t_4 = NULL; __Pyx_RefNannySetupContext("pybuffer_index", 0); - /* "View.MemoryView":908 + /* "View.MemoryView":912 * 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 # <<<<<<<<<<<<<< @@ -10897,7 +10955,7 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P */ __pyx_v_suboffset = -1L; - /* "View.MemoryView":909 + /* "View.MemoryView":913 * Py_ssize_t dim) except NULL: * cdef Py_ssize_t shape, stride, suboffset = -1 * cdef Py_ssize_t itemsize = view.itemsize # <<<<<<<<<<<<<< @@ -10907,7 +10965,7 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P __pyx_t_1 = __pyx_v_view->itemsize; __pyx_v_itemsize = __pyx_t_1; - /* "View.MemoryView":912 + /* "View.MemoryView":916 * cdef char *resultp * * if view.ndim == 0: # <<<<<<<<<<<<<< @@ -10917,7 +10975,7 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P __pyx_t_2 = ((__pyx_v_view->ndim == 0) != 0); if (__pyx_t_2) { - /* "View.MemoryView":913 + /* "View.MemoryView":917 * * if view.ndim == 0: * shape = view.len / itemsize # <<<<<<<<<<<<<< @@ -10926,15 +10984,15 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P */ if (unlikely(__pyx_v_itemsize == 0)) { PyErr_SetString(PyExc_ZeroDivisionError, "integer division or modulo by zero"); - __PYX_ERR(1, 913, __pyx_L1_error) + __PYX_ERR(1, 917, __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(1, 913, __pyx_L1_error) + __PYX_ERR(1, 917, __pyx_L1_error) } __pyx_v_shape = __Pyx_div_Py_ssize_t(__pyx_v_view->len, __pyx_v_itemsize); - /* "View.MemoryView":914 + /* "View.MemoryView":918 * if view.ndim == 0: * shape = view.len / itemsize * stride = itemsize # <<<<<<<<<<<<<< @@ -10943,7 +11001,7 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P */ __pyx_v_stride = __pyx_v_itemsize; - /* "View.MemoryView":912 + /* "View.MemoryView":916 * cdef char *resultp * * if view.ndim == 0: # <<<<<<<<<<<<<< @@ -10953,7 +11011,7 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P goto __pyx_L3; } - /* "View.MemoryView":916 + /* "View.MemoryView":920 * stride = itemsize * else: * shape = view.shape[dim] # <<<<<<<<<<<<<< @@ -10963,7 +11021,7 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P /*else*/ { __pyx_v_shape = (__pyx_v_view->shape[__pyx_v_dim]); - /* "View.MemoryView":917 + /* "View.MemoryView":921 * else: * shape = view.shape[dim] * stride = view.strides[dim] # <<<<<<<<<<<<<< @@ -10972,7 +11030,7 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P */ __pyx_v_stride = (__pyx_v_view->strides[__pyx_v_dim]); - /* "View.MemoryView":918 + /* "View.MemoryView":922 * shape = view.shape[dim] * stride = view.strides[dim] * if view.suboffsets != NULL: # <<<<<<<<<<<<<< @@ -10982,7 +11040,7 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P __pyx_t_2 = ((__pyx_v_view->suboffsets != NULL) != 0); if (__pyx_t_2) { - /* "View.MemoryView":919 + /* "View.MemoryView":923 * stride = view.strides[dim] * if view.suboffsets != NULL: * suboffset = view.suboffsets[dim] # <<<<<<<<<<<<<< @@ -10991,7 +11049,7 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P */ __pyx_v_suboffset = (__pyx_v_view->suboffsets[__pyx_v_dim]); - /* "View.MemoryView":918 + /* "View.MemoryView":922 * shape = view.shape[dim] * stride = view.strides[dim] * if view.suboffsets != NULL: # <<<<<<<<<<<<<< @@ -11002,7 +11060,7 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P } __pyx_L3:; - /* "View.MemoryView":921 + /* "View.MemoryView":925 * suboffset = view.suboffsets[dim] * * if index < 0: # <<<<<<<<<<<<<< @@ -11012,7 +11070,7 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P __pyx_t_2 = ((__pyx_v_index < 0) != 0); if (__pyx_t_2) { - /* "View.MemoryView":922 + /* "View.MemoryView":926 * * if index < 0: * index += view.shape[dim] # <<<<<<<<<<<<<< @@ -11021,7 +11079,7 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P */ __pyx_v_index = (__pyx_v_index + (__pyx_v_view->shape[__pyx_v_dim])); - /* "View.MemoryView":923 + /* "View.MemoryView":927 * if index < 0: * index += view.shape[dim] * if index < 0: # <<<<<<<<<<<<<< @@ -11031,26 +11089,26 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P __pyx_t_2 = ((__pyx_v_index < 0) != 0); if (unlikely(__pyx_t_2)) { - /* "View.MemoryView":924 + /* "View.MemoryView":928 * 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(1, 924, __pyx_L1_error) + __pyx_t_3 = PyInt_FromSsize_t(__pyx_v_dim); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 928, __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(1, 924, __pyx_L1_error) + __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(1, 928, __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(1, 924, __pyx_L1_error) + __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_IndexError, __pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 928, __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(1, 924, __pyx_L1_error) + __PYX_ERR(1, 928, __pyx_L1_error) - /* "View.MemoryView":923 + /* "View.MemoryView":927 * if index < 0: * index += view.shape[dim] * if index < 0: # <<<<<<<<<<<<<< @@ -11059,7 +11117,7 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P */ } - /* "View.MemoryView":921 + /* "View.MemoryView":925 * suboffset = view.suboffsets[dim] * * if index < 0: # <<<<<<<<<<<<<< @@ -11068,7 +11126,7 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P */ } - /* "View.MemoryView":926 + /* "View.MemoryView":930 * raise IndexError("Out of bounds on buffer access (axis %d)" % dim) * * if index >= shape: # <<<<<<<<<<<<<< @@ -11078,26 +11136,26 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P __pyx_t_2 = ((__pyx_v_index >= __pyx_v_shape) != 0); if (unlikely(__pyx_t_2)) { - /* "View.MemoryView":927 + /* "View.MemoryView":931 * * 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(1, 927, __pyx_L1_error) + __pyx_t_3 = PyInt_FromSsize_t(__pyx_v_dim); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 931, __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(1, 927, __pyx_L1_error) + __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(1, 931, __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(1, 927, __pyx_L1_error) + __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_IndexError, __pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 931, __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(1, 927, __pyx_L1_error) + __PYX_ERR(1, 931, __pyx_L1_error) - /* "View.MemoryView":926 + /* "View.MemoryView":930 * raise IndexError("Out of bounds on buffer access (axis %d)" % dim) * * if index >= shape: # <<<<<<<<<<<<<< @@ -11106,7 +11164,7 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P */ } - /* "View.MemoryView":929 + /* "View.MemoryView":933 * raise IndexError("Out of bounds on buffer access (axis %d)" % dim) * * resultp = bufp + index * stride # <<<<<<<<<<<<<< @@ -11115,7 +11173,7 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P */ __pyx_v_resultp = (__pyx_v_bufp + (__pyx_v_index * __pyx_v_stride)); - /* "View.MemoryView":930 + /* "View.MemoryView":934 * * resultp = bufp + index * stride * if suboffset >= 0: # <<<<<<<<<<<<<< @@ -11125,7 +11183,7 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P __pyx_t_2 = ((__pyx_v_suboffset >= 0) != 0); if (__pyx_t_2) { - /* "View.MemoryView":931 + /* "View.MemoryView":935 * resultp = bufp + index * stride * if suboffset >= 0: * resultp = ( resultp)[0] + suboffset # <<<<<<<<<<<<<< @@ -11134,7 +11192,7 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P */ __pyx_v_resultp = ((((char **)__pyx_v_resultp)[0]) + __pyx_v_suboffset); - /* "View.MemoryView":930 + /* "View.MemoryView":934 * * resultp = bufp + index * stride * if suboffset >= 0: # <<<<<<<<<<<<<< @@ -11143,7 +11201,7 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P */ } - /* "View.MemoryView":933 + /* "View.MemoryView":937 * resultp = ( resultp)[0] + suboffset * * return resultp # <<<<<<<<<<<<<< @@ -11153,7 +11211,7 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P __pyx_r = __pyx_v_resultp; goto __pyx_L0; - /* "View.MemoryView":906 + /* "View.MemoryView":910 * * @cname('__pyx_pybuffer_index') * cdef char *pybuffer_index(Py_buffer *view, char *bufp, Py_ssize_t index, # <<<<<<<<<<<<<< @@ -11172,7 +11230,7 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P return __pyx_r; } -/* "View.MemoryView":939 +/* "View.MemoryView":943 * * @cname('__pyx_memslice_transpose') * cdef int transpose_memslice(__Pyx_memviewslice *memslice) nogil except 0: # <<<<<<<<<<<<<< @@ -11197,7 +11255,7 @@ static int __pyx_memslice_transpose(__Pyx_memviewslice *__pyx_v_memslice) { int __pyx_t_8; int __pyx_t_9; - /* "View.MemoryView":940 + /* "View.MemoryView":944 * @cname('__pyx_memslice_transpose') * cdef int transpose_memslice(__Pyx_memviewslice *memslice) nogil except 0: * cdef int ndim = memslice.memview.view.ndim # <<<<<<<<<<<<<< @@ -11207,7 +11265,7 @@ static int __pyx_memslice_transpose(__Pyx_memviewslice *__pyx_v_memslice) { __pyx_t_1 = __pyx_v_memslice->memview->view.ndim; __pyx_v_ndim = __pyx_t_1; - /* "View.MemoryView":942 + /* "View.MemoryView":946 * cdef int ndim = memslice.memview.view.ndim * * cdef Py_ssize_t *shape = memslice.shape # <<<<<<<<<<<<<< @@ -11217,7 +11275,7 @@ static int __pyx_memslice_transpose(__Pyx_memviewslice *__pyx_v_memslice) { __pyx_t_2 = __pyx_v_memslice->shape; __pyx_v_shape = __pyx_t_2; - /* "View.MemoryView":943 + /* "View.MemoryView":947 * * cdef Py_ssize_t *shape = memslice.shape * cdef Py_ssize_t *strides = memslice.strides # <<<<<<<<<<<<<< @@ -11227,7 +11285,7 @@ static int __pyx_memslice_transpose(__Pyx_memviewslice *__pyx_v_memslice) { __pyx_t_2 = __pyx_v_memslice->strides; __pyx_v_strides = __pyx_t_2; - /* "View.MemoryView":947 + /* "View.MemoryView":951 * * cdef int i, j * for i in range(ndim / 2): # <<<<<<<<<<<<<< @@ -11239,7 +11297,7 @@ static int __pyx_memslice_transpose(__Pyx_memviewslice *__pyx_v_memslice) { for (__pyx_t_1 = 0; __pyx_t_1 < __pyx_t_4; __pyx_t_1+=1) { __pyx_v_i = __pyx_t_1; - /* "View.MemoryView":948 + /* "View.MemoryView":952 * cdef int i, j * for i in range(ndim / 2): * j = ndim - 1 - i # <<<<<<<<<<<<<< @@ -11248,7 +11306,7 @@ static int __pyx_memslice_transpose(__Pyx_memviewslice *__pyx_v_memslice) { */ __pyx_v_j = ((__pyx_v_ndim - 1) - __pyx_v_i); - /* "View.MemoryView":949 + /* "View.MemoryView":953 * for i in range(ndim / 2): * j = ndim - 1 - i * strides[i], strides[j] = strides[j], strides[i] # <<<<<<<<<<<<<< @@ -11260,7 +11318,7 @@ static int __pyx_memslice_transpose(__Pyx_memviewslice *__pyx_v_memslice) { (__pyx_v_strides[__pyx_v_i]) = __pyx_t_5; (__pyx_v_strides[__pyx_v_j]) = __pyx_t_6; - /* "View.MemoryView":950 + /* "View.MemoryView":954 * j = ndim - 1 - i * strides[i], strides[j] = strides[j], strides[i] * shape[i], shape[j] = shape[j], shape[i] # <<<<<<<<<<<<<< @@ -11272,7 +11330,7 @@ static int __pyx_memslice_transpose(__Pyx_memviewslice *__pyx_v_memslice) { (__pyx_v_shape[__pyx_v_i]) = __pyx_t_6; (__pyx_v_shape[__pyx_v_j]) = __pyx_t_5; - /* "View.MemoryView":952 + /* "View.MemoryView":956 * shape[i], shape[j] = shape[j], shape[i] * * if memslice.suboffsets[i] >= 0 or memslice.suboffsets[j] >= 0: # <<<<<<<<<<<<<< @@ -11290,16 +11348,16 @@ static int __pyx_memslice_transpose(__Pyx_memviewslice *__pyx_v_memslice) { __pyx_L6_bool_binop_done:; if (__pyx_t_7) { - /* "View.MemoryView":953 + /* "View.MemoryView":957 * * 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(1, 953, __pyx_L1_error) + __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(1, 957, __pyx_L1_error) - /* "View.MemoryView":952 + /* "View.MemoryView":956 * shape[i], shape[j] = shape[j], shape[i] * * if memslice.suboffsets[i] >= 0 or memslice.suboffsets[j] >= 0: # <<<<<<<<<<<<<< @@ -11309,7 +11367,7 @@ static int __pyx_memslice_transpose(__Pyx_memviewslice *__pyx_v_memslice) { } } - /* "View.MemoryView":955 + /* "View.MemoryView":959 * _err(ValueError, "Cannot transpose memoryview with indirect dimensions") * * return 1 # <<<<<<<<<<<<<< @@ -11319,7 +11377,7 @@ static int __pyx_memslice_transpose(__Pyx_memviewslice *__pyx_v_memslice) { __pyx_r = 1; goto __pyx_L0; - /* "View.MemoryView":939 + /* "View.MemoryView":943 * * @cname('__pyx_memslice_transpose') * cdef int transpose_memslice(__Pyx_memviewslice *memslice) nogil except 0: # <<<<<<<<<<<<<< @@ -11343,7 +11401,7 @@ static int __pyx_memslice_transpose(__Pyx_memviewslice *__pyx_v_memslice) { return __pyx_r; } -/* "View.MemoryView":972 +/* "View.MemoryView":976 * cdef int (*to_dtype_func)(char *, object) except 0 * * def __dealloc__(self): # <<<<<<<<<<<<<< @@ -11366,7 +11424,7 @@ static void __pyx_memoryviewslice___pyx_pf_15View_dot_MemoryView_16_memoryviewsl __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__dealloc__", 0); - /* "View.MemoryView":973 + /* "View.MemoryView":977 * * def __dealloc__(self): * __PYX_XDEC_MEMVIEW(&self.from_slice, 1) # <<<<<<<<<<<<<< @@ -11375,7 +11433,7 @@ static void __pyx_memoryviewslice___pyx_pf_15View_dot_MemoryView_16_memoryviewsl */ __PYX_XDEC_MEMVIEW((&__pyx_v_self->from_slice), 1); - /* "View.MemoryView":972 + /* "View.MemoryView":976 * cdef int (*to_dtype_func)(char *, object) except 0 * * def __dealloc__(self): # <<<<<<<<<<<<<< @@ -11387,7 +11445,7 @@ static void __pyx_memoryviewslice___pyx_pf_15View_dot_MemoryView_16_memoryviewsl __Pyx_RefNannyFinishContext(); } -/* "View.MemoryView":975 +/* "View.MemoryView":979 * __PYX_XDEC_MEMVIEW(&self.from_slice, 1) * * cdef convert_item_to_object(self, char *itemp): # <<<<<<<<<<<<<< @@ -11402,7 +11460,7 @@ static PyObject *__pyx_memoryviewslice_convert_item_to_object(struct __pyx_memor PyObject *__pyx_t_2 = NULL; __Pyx_RefNannySetupContext("convert_item_to_object", 0); - /* "View.MemoryView":976 + /* "View.MemoryView":980 * * cdef convert_item_to_object(self, char *itemp): * if self.to_object_func != NULL: # <<<<<<<<<<<<<< @@ -11412,7 +11470,7 @@ static PyObject *__pyx_memoryviewslice_convert_item_to_object(struct __pyx_memor __pyx_t_1 = ((__pyx_v_self->to_object_func != NULL) != 0); if (__pyx_t_1) { - /* "View.MemoryView":977 + /* "View.MemoryView":981 * cdef convert_item_to_object(self, char *itemp): * if self.to_object_func != NULL: * return self.to_object_func(itemp) # <<<<<<<<<<<<<< @@ -11420,13 +11478,13 @@ static PyObject *__pyx_memoryviewslice_convert_item_to_object(struct __pyx_memor * 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(1, 977, __pyx_L1_error) + __pyx_t_2 = __pyx_v_self->to_object_func(__pyx_v_itemp); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 981, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __pyx_r = __pyx_t_2; __pyx_t_2 = 0; goto __pyx_L0; - /* "View.MemoryView":976 + /* "View.MemoryView":980 * * cdef convert_item_to_object(self, char *itemp): * if self.to_object_func != NULL: # <<<<<<<<<<<<<< @@ -11435,7 +11493,7 @@ static PyObject *__pyx_memoryviewslice_convert_item_to_object(struct __pyx_memor */ } - /* "View.MemoryView":979 + /* "View.MemoryView":983 * return self.to_object_func(itemp) * else: * return memoryview.convert_item_to_object(self, itemp) # <<<<<<<<<<<<<< @@ -11444,14 +11502,14 @@ static PyObject *__pyx_memoryviewslice_convert_item_to_object(struct __pyx_memor */ /*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(1, 979, __pyx_L1_error) + __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(1, 983, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __pyx_r = __pyx_t_2; __pyx_t_2 = 0; goto __pyx_L0; } - /* "View.MemoryView":975 + /* "View.MemoryView":979 * __PYX_XDEC_MEMVIEW(&self.from_slice, 1) * * cdef convert_item_to_object(self, char *itemp): # <<<<<<<<<<<<<< @@ -11470,7 +11528,7 @@ static PyObject *__pyx_memoryviewslice_convert_item_to_object(struct __pyx_memor return __pyx_r; } -/* "View.MemoryView":981 +/* "View.MemoryView":985 * return memoryview.convert_item_to_object(self, itemp) * * cdef assign_item_from_object(self, char *itemp, object value): # <<<<<<<<<<<<<< @@ -11486,7 +11544,7 @@ static PyObject *__pyx_memoryviewslice_assign_item_from_object(struct __pyx_memo PyObject *__pyx_t_3 = NULL; __Pyx_RefNannySetupContext("assign_item_from_object", 0); - /* "View.MemoryView":982 + /* "View.MemoryView":986 * * cdef assign_item_from_object(self, char *itemp, object value): * if self.to_dtype_func != NULL: # <<<<<<<<<<<<<< @@ -11496,16 +11554,16 @@ static PyObject *__pyx_memoryviewslice_assign_item_from_object(struct __pyx_memo __pyx_t_1 = ((__pyx_v_self->to_dtype_func != NULL) != 0); if (__pyx_t_1) { - /* "View.MemoryView":983 + /* "View.MemoryView":987 * 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(1, 983, __pyx_L1_error) + __pyx_t_2 = __pyx_v_self->to_dtype_func(__pyx_v_itemp, __pyx_v_value); if (unlikely(__pyx_t_2 == ((int)0))) __PYX_ERR(1, 987, __pyx_L1_error) - /* "View.MemoryView":982 + /* "View.MemoryView":986 * * cdef assign_item_from_object(self, char *itemp, object value): * if self.to_dtype_func != NULL: # <<<<<<<<<<<<<< @@ -11515,7 +11573,7 @@ static PyObject *__pyx_memoryviewslice_assign_item_from_object(struct __pyx_memo goto __pyx_L3; } - /* "View.MemoryView":985 + /* "View.MemoryView":989 * self.to_dtype_func(itemp, value) * else: * memoryview.assign_item_from_object(self, itemp, value) # <<<<<<<<<<<<<< @@ -11523,13 +11581,13 @@ static PyObject *__pyx_memoryviewslice_assign_item_from_object(struct __pyx_memo * @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(1, 985, __pyx_L1_error) + __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(1, 989, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; } __pyx_L3:; - /* "View.MemoryView":981 + /* "View.MemoryView":985 * return memoryview.convert_item_to_object(self, itemp) * * cdef assign_item_from_object(self, char *itemp, object value): # <<<<<<<<<<<<<< @@ -11550,7 +11608,7 @@ static PyObject *__pyx_memoryviewslice_assign_item_from_object(struct __pyx_memo return __pyx_r; } -/* "View.MemoryView":988 +/* "View.MemoryView":992 * * @property * def base(self): # <<<<<<<<<<<<<< @@ -11576,7 +11634,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_16_memoryviewslice_4base___get__ __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__get__", 0); - /* "View.MemoryView":989 + /* "View.MemoryView":993 * @property * def base(self): * return self.from_object # <<<<<<<<<<<<<< @@ -11588,7 +11646,7 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_16_memoryviewslice_4base___get__ __pyx_r = __pyx_v_self->from_object; goto __pyx_L0; - /* "View.MemoryView":988 + /* "View.MemoryView":992 * * @property * def base(self): # <<<<<<<<<<<<<< @@ -11710,7 +11768,7 @@ static PyObject *__pyx_pf___pyx_memoryviewslice_2__setstate_cython__(CYTHON_UNUS return __pyx_r; } -/* "View.MemoryView":995 +/* "View.MemoryView":999 * * @cname('__pyx_memoryview_fromslice') * cdef memoryview_fromslice(__Pyx_memviewslice memviewslice, # <<<<<<<<<<<<<< @@ -11735,7 +11793,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl Py_ssize_t __pyx_t_9; __Pyx_RefNannySetupContext("memoryview_fromslice", 0); - /* "View.MemoryView":1003 + /* "View.MemoryView":1007 * cdef _memoryviewslice result * * if memviewslice.memview == Py_None: # <<<<<<<<<<<<<< @@ -11745,7 +11803,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl __pyx_t_1 = ((((PyObject *)__pyx_v_memviewslice.memview) == Py_None) != 0); if (__pyx_t_1) { - /* "View.MemoryView":1004 + /* "View.MemoryView":1008 * * if memviewslice.memview == Py_None: * return None # <<<<<<<<<<<<<< @@ -11756,7 +11814,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl __pyx_r = Py_None; __Pyx_INCREF(Py_None); goto __pyx_L0; - /* "View.MemoryView":1003 + /* "View.MemoryView":1007 * cdef _memoryviewslice result * * if memviewslice.memview == Py_None: # <<<<<<<<<<<<<< @@ -11765,16 +11823,16 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl */ } - /* "View.MemoryView":1009 + /* "View.MemoryView":1013 * * * 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(1, 1009, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyBool_FromLong(__pyx_v_dtype_is_object); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1013, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 1009, __pyx_L1_error) + __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 1013, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_INCREF(Py_None); __Pyx_GIVEREF(Py_None); @@ -11785,13 +11843,13 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl __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(1, 1009, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_Call(((PyObject *)__pyx_memoryviewslice_type), __pyx_t_3, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1013, __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":1011 + /* "View.MemoryView":1015 * result = _memoryviewslice(None, 0, dtype_is_object) * * result.from_slice = memviewslice # <<<<<<<<<<<<<< @@ -11800,7 +11858,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl */ __pyx_v_result->from_slice = __pyx_v_memviewslice; - /* "View.MemoryView":1012 + /* "View.MemoryView":1016 * * result.from_slice = memviewslice * __PYX_INC_MEMVIEW(&memviewslice, 1) # <<<<<<<<<<<<<< @@ -11809,14 +11867,14 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl */ __PYX_INC_MEMVIEW((&__pyx_v_memviewslice), 1); - /* "View.MemoryView":1014 + /* "View.MemoryView":1018 * __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(1, 1014, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_memviewslice.memview), __pyx_n_s_base); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1018, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_GIVEREF(__pyx_t_2); __Pyx_GOTREF(__pyx_v_result->from_object); @@ -11824,7 +11882,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl __pyx_v_result->from_object = __pyx_t_2; __pyx_t_2 = 0; - /* "View.MemoryView":1015 + /* "View.MemoryView":1019 * * result.from_object = ( memviewslice.memview).base * result.typeinfo = memviewslice.memview.typeinfo # <<<<<<<<<<<<<< @@ -11834,7 +11892,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl __pyx_t_4 = __pyx_v_memviewslice.memview->typeinfo; __pyx_v_result->__pyx_base.typeinfo = __pyx_t_4; - /* "View.MemoryView":1017 + /* "View.MemoryView":1021 * result.typeinfo = memviewslice.memview.typeinfo * * result.view = memviewslice.memview.view # <<<<<<<<<<<<<< @@ -11844,7 +11902,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl __pyx_t_5 = __pyx_v_memviewslice.memview->view; __pyx_v_result->__pyx_base.view = __pyx_t_5; - /* "View.MemoryView":1018 + /* "View.MemoryView":1022 * * result.view = memviewslice.memview.view * result.view.buf = memviewslice.data # <<<<<<<<<<<<<< @@ -11853,7 +11911,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl */ __pyx_v_result->__pyx_base.view.buf = ((void *)__pyx_v_memviewslice.data); - /* "View.MemoryView":1019 + /* "View.MemoryView":1023 * result.view = memviewslice.memview.view * result.view.buf = memviewslice.data * result.view.ndim = ndim # <<<<<<<<<<<<<< @@ -11862,7 +11920,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl */ __pyx_v_result->__pyx_base.view.ndim = __pyx_v_ndim; - /* "View.MemoryView":1020 + /* "View.MemoryView":1024 * result.view.buf = memviewslice.data * result.view.ndim = ndim * (<__pyx_buffer *> &result.view).obj = Py_None # <<<<<<<<<<<<<< @@ -11871,7 +11929,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl */ ((Py_buffer *)(&__pyx_v_result->__pyx_base.view))->obj = Py_None; - /* "View.MemoryView":1021 + /* "View.MemoryView":1025 * result.view.ndim = ndim * (<__pyx_buffer *> &result.view).obj = Py_None * Py_INCREF(Py_None) # <<<<<<<<<<<<<< @@ -11880,7 +11938,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl */ Py_INCREF(Py_None); - /* "View.MemoryView":1023 + /* "View.MemoryView":1027 * Py_INCREF(Py_None) * * if (memviewslice.memview).flags & PyBUF_WRITABLE: # <<<<<<<<<<<<<< @@ -11890,7 +11948,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl __pyx_t_1 = ((((struct __pyx_memoryview_obj *)__pyx_v_memviewslice.memview)->flags & PyBUF_WRITABLE) != 0); if (__pyx_t_1) { - /* "View.MemoryView":1024 + /* "View.MemoryView":1028 * * if (memviewslice.memview).flags & PyBUF_WRITABLE: * result.flags = PyBUF_RECORDS # <<<<<<<<<<<<<< @@ -11899,7 +11957,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl */ __pyx_v_result->__pyx_base.flags = PyBUF_RECORDS; - /* "View.MemoryView":1023 + /* "View.MemoryView":1027 * Py_INCREF(Py_None) * * if (memviewslice.memview).flags & PyBUF_WRITABLE: # <<<<<<<<<<<<<< @@ -11909,7 +11967,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl goto __pyx_L4; } - /* "View.MemoryView":1026 + /* "View.MemoryView":1030 * result.flags = PyBUF_RECORDS * else: * result.flags = PyBUF_RECORDS_RO # <<<<<<<<<<<<<< @@ -11921,7 +11979,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl } __pyx_L4:; - /* "View.MemoryView":1028 + /* "View.MemoryView":1032 * result.flags = PyBUF_RECORDS_RO * * result.view.shape = result.from_slice.shape # <<<<<<<<<<<<<< @@ -11930,7 +11988,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl */ __pyx_v_result->__pyx_base.view.shape = ((Py_ssize_t *)__pyx_v_result->from_slice.shape); - /* "View.MemoryView":1029 + /* "View.MemoryView":1033 * * result.view.shape = result.from_slice.shape * result.view.strides = result.from_slice.strides # <<<<<<<<<<<<<< @@ -11939,7 +11997,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl */ __pyx_v_result->__pyx_base.view.strides = ((Py_ssize_t *)__pyx_v_result->from_slice.strides); - /* "View.MemoryView":1032 + /* "View.MemoryView":1036 * * * result.view.suboffsets = NULL # <<<<<<<<<<<<<< @@ -11948,7 +12006,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl */ __pyx_v_result->__pyx_base.view.suboffsets = NULL; - /* "View.MemoryView":1033 + /* "View.MemoryView":1037 * * result.view.suboffsets = NULL * for suboffset in result.from_slice.suboffsets[:ndim]: # <<<<<<<<<<<<<< @@ -11960,7 +12018,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl __pyx_t_6 = __pyx_t_8; __pyx_v_suboffset = (__pyx_t_6[0]); - /* "View.MemoryView":1034 + /* "View.MemoryView":1038 * result.view.suboffsets = NULL * for suboffset in result.from_slice.suboffsets[:ndim]: * if suboffset >= 0: # <<<<<<<<<<<<<< @@ -11970,7 +12028,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl __pyx_t_1 = ((__pyx_v_suboffset >= 0) != 0); if (__pyx_t_1) { - /* "View.MemoryView":1035 + /* "View.MemoryView":1039 * for suboffset in result.from_slice.suboffsets[:ndim]: * if suboffset >= 0: * result.view.suboffsets = result.from_slice.suboffsets # <<<<<<<<<<<<<< @@ -11979,7 +12037,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl */ __pyx_v_result->__pyx_base.view.suboffsets = ((Py_ssize_t *)__pyx_v_result->from_slice.suboffsets); - /* "View.MemoryView":1036 + /* "View.MemoryView":1040 * if suboffset >= 0: * result.view.suboffsets = result.from_slice.suboffsets * break # <<<<<<<<<<<<<< @@ -11988,7 +12046,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl */ goto __pyx_L6_break; - /* "View.MemoryView":1034 + /* "View.MemoryView":1038 * result.view.suboffsets = NULL * for suboffset in result.from_slice.suboffsets[:ndim]: * if suboffset >= 0: # <<<<<<<<<<<<<< @@ -11999,7 +12057,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl } __pyx_L6_break:; - /* "View.MemoryView":1038 + /* "View.MemoryView":1042 * break * * result.view.len = result.view.itemsize # <<<<<<<<<<<<<< @@ -12009,7 +12067,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl __pyx_t_9 = __pyx_v_result->__pyx_base.view.itemsize; __pyx_v_result->__pyx_base.view.len = __pyx_t_9; - /* "View.MemoryView":1039 + /* "View.MemoryView":1043 * * result.view.len = result.view.itemsize * for length in result.view.shape[:ndim]: # <<<<<<<<<<<<<< @@ -12019,29 +12077,29 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl __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(1, 1039, __pyx_L1_error) + __pyx_t_2 = PyInt_FromSsize_t((__pyx_t_6[0])); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1043, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_XDECREF_SET(__pyx_v_length, __pyx_t_2); __pyx_t_2 = 0; - /* "View.MemoryView":1040 + /* "View.MemoryView":1044 * 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(1, 1040, __pyx_L1_error) + __pyx_t_2 = PyInt_FromSsize_t(__pyx_v_result->__pyx_base.view.len); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1044, __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(1, 1040, __pyx_L1_error) + __pyx_t_3 = PyNumber_InPlaceMultiply(__pyx_t_2, __pyx_v_length); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 1044, __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(1, 1040, __pyx_L1_error) + __pyx_t_9 = __Pyx_PyIndex_AsSsize_t(__pyx_t_3); if (unlikely((__pyx_t_9 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(1, 1044, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_v_result->__pyx_base.view.len = __pyx_t_9; } - /* "View.MemoryView":1042 + /* "View.MemoryView":1046 * result.view.len *= length * * result.to_object_func = to_object_func # <<<<<<<<<<<<<< @@ -12050,7 +12108,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl */ __pyx_v_result->to_object_func = __pyx_v_to_object_func; - /* "View.MemoryView":1043 + /* "View.MemoryView":1047 * * result.to_object_func = to_object_func * result.to_dtype_func = to_dtype_func # <<<<<<<<<<<<<< @@ -12059,7 +12117,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl */ __pyx_v_result->to_dtype_func = __pyx_v_to_dtype_func; - /* "View.MemoryView":1045 + /* "View.MemoryView":1049 * result.to_dtype_func = to_dtype_func * * return result # <<<<<<<<<<<<<< @@ -12071,7 +12129,7 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl __pyx_r = ((PyObject *)__pyx_v_result); goto __pyx_L0; - /* "View.MemoryView":995 + /* "View.MemoryView":999 * * @cname('__pyx_memoryview_fromslice') * cdef memoryview_fromslice(__Pyx_memviewslice memviewslice, # <<<<<<<<<<<<<< @@ -12093,11 +12151,11 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl return __pyx_r; } -/* "View.MemoryView":1048 +/* "View.MemoryView":1052 * * @cname('__pyx_memoryview_get_slice_from_memoryview') * cdef __Pyx_memviewslice *get_slice_from_memview(memoryview memview, # <<<<<<<<<<<<<< - * __Pyx_memviewslice *mslice): + * __Pyx_memviewslice *mslice) except NULL: * cdef _memoryviewslice obj */ @@ -12110,8 +12168,8 @@ static __Pyx_memviewslice *__pyx_memoryview_get_slice_from_memoryview(struct __p PyObject *__pyx_t_3 = NULL; __Pyx_RefNannySetupContext("get_slice_from_memview", 0); - /* "View.MemoryView":1051 - * __Pyx_memviewslice *mslice): + /* "View.MemoryView":1055 + * __Pyx_memviewslice *mslice) except NULL: * cdef _memoryviewslice obj * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< * obj = memview @@ -12121,20 +12179,20 @@ static __Pyx_memviewslice *__pyx_memoryview_get_slice_from_memoryview(struct __p __pyx_t_2 = (__pyx_t_1 != 0); if (__pyx_t_2) { - /* "View.MemoryView":1052 + /* "View.MemoryView":1056 * 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(1, 1052, __pyx_L1_error) + if (!(likely(((((PyObject *)__pyx_v_memview)) == Py_None) || likely(__Pyx_TypeTest(((PyObject *)__pyx_v_memview), __pyx_memoryviewslice_type))))) __PYX_ERR(1, 1056, __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":1053 + /* "View.MemoryView":1057 * if isinstance(memview, _memoryviewslice): * obj = memview * return &obj.from_slice # <<<<<<<<<<<<<< @@ -12144,8 +12202,8 @@ static __Pyx_memviewslice *__pyx_memoryview_get_slice_from_memoryview(struct __p __pyx_r = (&__pyx_v_obj->from_slice); goto __pyx_L0; - /* "View.MemoryView":1051 - * __Pyx_memviewslice *mslice): + /* "View.MemoryView":1055 + * __Pyx_memviewslice *mslice) except NULL: * cdef _memoryviewslice obj * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< * obj = memview @@ -12153,7 +12211,7 @@ static __Pyx_memviewslice *__pyx_memoryview_get_slice_from_memoryview(struct __p */ } - /* "View.MemoryView":1055 + /* "View.MemoryView":1059 * return &obj.from_slice * else: * slice_copy(memview, mslice) # <<<<<<<<<<<<<< @@ -12163,7 +12221,7 @@ static __Pyx_memviewslice *__pyx_memoryview_get_slice_from_memoryview(struct __p /*else*/ { __pyx_memoryview_slice_copy(__pyx_v_memview, __pyx_v_mslice); - /* "View.MemoryView":1056 + /* "View.MemoryView":1060 * else: * slice_copy(memview, mslice) * return mslice # <<<<<<<<<<<<<< @@ -12174,26 +12232,26 @@ static __Pyx_memviewslice *__pyx_memoryview_get_slice_from_memoryview(struct __p goto __pyx_L0; } - /* "View.MemoryView":1048 + /* "View.MemoryView":1052 * * @cname('__pyx_memoryview_get_slice_from_memoryview') * cdef __Pyx_memviewslice *get_slice_from_memview(memoryview memview, # <<<<<<<<<<<<<< - * __Pyx_memviewslice *mslice): + * __Pyx_memviewslice *mslice) except NULL: * cdef _memoryviewslice obj */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_3); - __Pyx_WriteUnraisable("View.MemoryView.get_slice_from_memview", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0); - __pyx_r = 0; + __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":1059 +/* "View.MemoryView":1063 * * @cname('__pyx_memoryview_slice_copy') * cdef void slice_copy(memoryview memview, __Pyx_memviewslice *dst): # <<<<<<<<<<<<<< @@ -12214,7 +12272,7 @@ static void __pyx_memoryview_slice_copy(struct __pyx_memoryview_obj *__pyx_v_mem Py_ssize_t __pyx_t_5; __Pyx_RefNannySetupContext("slice_copy", 0); - /* "View.MemoryView":1063 + /* "View.MemoryView":1067 * cdef (Py_ssize_t*) shape, strides, suboffsets * * shape = memview.view.shape # <<<<<<<<<<<<<< @@ -12224,7 +12282,7 @@ static void __pyx_memoryview_slice_copy(struct __pyx_memoryview_obj *__pyx_v_mem __pyx_t_1 = __pyx_v_memview->view.shape; __pyx_v_shape = __pyx_t_1; - /* "View.MemoryView":1064 + /* "View.MemoryView":1068 * * shape = memview.view.shape * strides = memview.view.strides # <<<<<<<<<<<<<< @@ -12234,7 +12292,7 @@ static void __pyx_memoryview_slice_copy(struct __pyx_memoryview_obj *__pyx_v_mem __pyx_t_1 = __pyx_v_memview->view.strides; __pyx_v_strides = __pyx_t_1; - /* "View.MemoryView":1065 + /* "View.MemoryView":1069 * shape = memview.view.shape * strides = memview.view.strides * suboffsets = memview.view.suboffsets # <<<<<<<<<<<<<< @@ -12244,7 +12302,7 @@ static void __pyx_memoryview_slice_copy(struct __pyx_memoryview_obj *__pyx_v_mem __pyx_t_1 = __pyx_v_memview->view.suboffsets; __pyx_v_suboffsets = __pyx_t_1; - /* "View.MemoryView":1067 + /* "View.MemoryView":1071 * suboffsets = memview.view.suboffsets * * dst.memview = <__pyx_memoryview *> memview # <<<<<<<<<<<<<< @@ -12253,7 +12311,7 @@ static void __pyx_memoryview_slice_copy(struct __pyx_memoryview_obj *__pyx_v_mem */ __pyx_v_dst->memview = ((struct __pyx_memoryview_obj *)__pyx_v_memview); - /* "View.MemoryView":1068 + /* "View.MemoryView":1072 * * dst.memview = <__pyx_memoryview *> memview * dst.data = memview.view.buf # <<<<<<<<<<<<<< @@ -12262,7 +12320,7 @@ static void __pyx_memoryview_slice_copy(struct __pyx_memoryview_obj *__pyx_v_mem */ __pyx_v_dst->data = ((char *)__pyx_v_memview->view.buf); - /* "View.MemoryView":1070 + /* "View.MemoryView":1074 * dst.data = memview.view.buf * * for dim in range(memview.view.ndim): # <<<<<<<<<<<<<< @@ -12274,7 +12332,7 @@ static void __pyx_memoryview_slice_copy(struct __pyx_memoryview_obj *__pyx_v_mem for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { __pyx_v_dim = __pyx_t_4; - /* "View.MemoryView":1071 + /* "View.MemoryView":1075 * * for dim in range(memview.view.ndim): * dst.shape[dim] = shape[dim] # <<<<<<<<<<<<<< @@ -12283,7 +12341,7 @@ static void __pyx_memoryview_slice_copy(struct __pyx_memoryview_obj *__pyx_v_mem */ (__pyx_v_dst->shape[__pyx_v_dim]) = (__pyx_v_shape[__pyx_v_dim]); - /* "View.MemoryView":1072 + /* "View.MemoryView":1076 * for dim in range(memview.view.ndim): * dst.shape[dim] = shape[dim] * dst.strides[dim] = strides[dim] # <<<<<<<<<<<<<< @@ -12292,7 +12350,7 @@ static void __pyx_memoryview_slice_copy(struct __pyx_memoryview_obj *__pyx_v_mem */ (__pyx_v_dst->strides[__pyx_v_dim]) = (__pyx_v_strides[__pyx_v_dim]); - /* "View.MemoryView":1073 + /* "View.MemoryView":1077 * dst.shape[dim] = shape[dim] * dst.strides[dim] = strides[dim] * dst.suboffsets[dim] = suboffsets[dim] if suboffsets else -1 # <<<<<<<<<<<<<< @@ -12307,7 +12365,7 @@ static void __pyx_memoryview_slice_copy(struct __pyx_memoryview_obj *__pyx_v_mem (__pyx_v_dst->suboffsets[__pyx_v_dim]) = __pyx_t_5; } - /* "View.MemoryView":1059 + /* "View.MemoryView":1063 * * @cname('__pyx_memoryview_slice_copy') * cdef void slice_copy(memoryview memview, __Pyx_memviewslice *dst): # <<<<<<<<<<<<<< @@ -12319,7 +12377,7 @@ static void __pyx_memoryview_slice_copy(struct __pyx_memoryview_obj *__pyx_v_mem __Pyx_RefNannyFinishContext(); } -/* "View.MemoryView":1076 +/* "View.MemoryView":1080 * * @cname('__pyx_memoryview_copy_object') * cdef memoryview_copy(memoryview memview): # <<<<<<<<<<<<<< @@ -12334,7 +12392,7 @@ static PyObject *__pyx_memoryview_copy_object(struct __pyx_memoryview_obj *__pyx PyObject *__pyx_t_1 = NULL; __Pyx_RefNannySetupContext("memoryview_copy", 0); - /* "View.MemoryView":1079 + /* "View.MemoryView":1083 * "Create a new memoryview object" * cdef __Pyx_memviewslice memviewslice * slice_copy(memview, &memviewslice) # <<<<<<<<<<<<<< @@ -12343,7 +12401,7 @@ static PyObject *__pyx_memoryview_copy_object(struct __pyx_memoryview_obj *__pyx */ __pyx_memoryview_slice_copy(__pyx_v_memview, (&__pyx_v_memviewslice)); - /* "View.MemoryView":1080 + /* "View.MemoryView":1084 * cdef __Pyx_memviewslice memviewslice * slice_copy(memview, &memviewslice) * return memoryview_copy_from_slice(memview, &memviewslice) # <<<<<<<<<<<<<< @@ -12351,13 +12409,13 @@ static PyObject *__pyx_memoryview_copy_object(struct __pyx_memoryview_obj *__pyx * @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(1, 1080, __pyx_L1_error) + __pyx_t_1 = __pyx_memoryview_copy_object_from_slice(__pyx_v_memview, (&__pyx_v_memviewslice)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 1084, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; - /* "View.MemoryView":1076 + /* "View.MemoryView":1080 * * @cname('__pyx_memoryview_copy_object') * cdef memoryview_copy(memoryview memview): # <<<<<<<<<<<<<< @@ -12376,7 +12434,7 @@ static PyObject *__pyx_memoryview_copy_object(struct __pyx_memoryview_obj *__pyx return __pyx_r; } -/* "View.MemoryView":1083 +/* "View.MemoryView":1087 * * @cname('__pyx_memoryview_copy_object_from_slice') * cdef memoryview_copy_from_slice(memoryview memview, __Pyx_memviewslice *memviewslice): # <<<<<<<<<<<<<< @@ -12396,7 +12454,7 @@ static PyObject *__pyx_memoryview_copy_object_from_slice(struct __pyx_memoryview PyObject *__pyx_t_5 = NULL; __Pyx_RefNannySetupContext("memoryview_copy_from_slice", 0); - /* "View.MemoryView":1090 + /* "View.MemoryView":1094 * cdef int (*to_dtype_func)(char *, object) except 0 * * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< @@ -12407,7 +12465,7 @@ static PyObject *__pyx_memoryview_copy_object_from_slice(struct __pyx_memoryview __pyx_t_2 = (__pyx_t_1 != 0); if (__pyx_t_2) { - /* "View.MemoryView":1091 + /* "View.MemoryView":1095 * * if isinstance(memview, _memoryviewslice): * to_object_func = (<_memoryviewslice> memview).to_object_func # <<<<<<<<<<<<<< @@ -12417,7 +12475,7 @@ static PyObject *__pyx_memoryview_copy_object_from_slice(struct __pyx_memoryview __pyx_t_3 = ((struct __pyx_memoryviewslice_obj *)__pyx_v_memview)->to_object_func; __pyx_v_to_object_func = __pyx_t_3; - /* "View.MemoryView":1092 + /* "View.MemoryView":1096 * if isinstance(memview, _memoryviewslice): * to_object_func = (<_memoryviewslice> memview).to_object_func * to_dtype_func = (<_memoryviewslice> memview).to_dtype_func # <<<<<<<<<<<<<< @@ -12427,7 +12485,7 @@ static PyObject *__pyx_memoryview_copy_object_from_slice(struct __pyx_memoryview __pyx_t_4 = ((struct __pyx_memoryviewslice_obj *)__pyx_v_memview)->to_dtype_func; __pyx_v_to_dtype_func = __pyx_t_4; - /* "View.MemoryView":1090 + /* "View.MemoryView":1094 * cdef int (*to_dtype_func)(char *, object) except 0 * * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< @@ -12437,7 +12495,7 @@ static PyObject *__pyx_memoryview_copy_object_from_slice(struct __pyx_memoryview goto __pyx_L3; } - /* "View.MemoryView":1094 + /* "View.MemoryView":1098 * to_dtype_func = (<_memoryviewslice> memview).to_dtype_func * else: * to_object_func = NULL # <<<<<<<<<<<<<< @@ -12447,7 +12505,7 @@ static PyObject *__pyx_memoryview_copy_object_from_slice(struct __pyx_memoryview /*else*/ { __pyx_v_to_object_func = NULL; - /* "View.MemoryView":1095 + /* "View.MemoryView":1099 * else: * to_object_func = NULL * to_dtype_func = NULL # <<<<<<<<<<<<<< @@ -12458,7 +12516,7 @@ static PyObject *__pyx_memoryview_copy_object_from_slice(struct __pyx_memoryview } __pyx_L3:; - /* "View.MemoryView":1097 + /* "View.MemoryView":1101 * to_dtype_func = NULL * * return memoryview_fromslice(memviewslice[0], memview.view.ndim, # <<<<<<<<<<<<<< @@ -12467,20 +12525,20 @@ static PyObject *__pyx_memoryview_copy_object_from_slice(struct __pyx_memoryview */ __Pyx_XDECREF(__pyx_r); - /* "View.MemoryView":1099 + /* "View.MemoryView":1103 * 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(1, 1097, __pyx_L1_error) + __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(1, 1101, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_5); __pyx_r = __pyx_t_5; __pyx_t_5 = 0; goto __pyx_L0; - /* "View.MemoryView":1083 + /* "View.MemoryView":1087 * * @cname('__pyx_memoryview_copy_object_from_slice') * cdef memoryview_copy_from_slice(memoryview memview, __Pyx_memviewslice *memviewslice): # <<<<<<<<<<<<<< @@ -12499,7 +12557,7 @@ static PyObject *__pyx_memoryview_copy_object_from_slice(struct __pyx_memoryview return __pyx_r; } -/* "View.MemoryView":1105 +/* "View.MemoryView":1109 * * * cdef Py_ssize_t abs_py_ssize_t(Py_ssize_t arg) nogil: # <<<<<<<<<<<<<< @@ -12511,7 +12569,7 @@ 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":1106 + /* "View.MemoryView":1110 * * cdef Py_ssize_t abs_py_ssize_t(Py_ssize_t arg) nogil: * if arg < 0: # <<<<<<<<<<<<<< @@ -12521,7 +12579,7 @@ static Py_ssize_t abs_py_ssize_t(Py_ssize_t __pyx_v_arg) { __pyx_t_1 = ((__pyx_v_arg < 0) != 0); if (__pyx_t_1) { - /* "View.MemoryView":1107 + /* "View.MemoryView":1111 * cdef Py_ssize_t abs_py_ssize_t(Py_ssize_t arg) nogil: * if arg < 0: * return -arg # <<<<<<<<<<<<<< @@ -12531,7 +12589,7 @@ static Py_ssize_t abs_py_ssize_t(Py_ssize_t __pyx_v_arg) { __pyx_r = (-__pyx_v_arg); goto __pyx_L0; - /* "View.MemoryView":1106 + /* "View.MemoryView":1110 * * cdef Py_ssize_t abs_py_ssize_t(Py_ssize_t arg) nogil: * if arg < 0: # <<<<<<<<<<<<<< @@ -12540,7 +12598,7 @@ static Py_ssize_t abs_py_ssize_t(Py_ssize_t __pyx_v_arg) { */ } - /* "View.MemoryView":1109 + /* "View.MemoryView":1113 * return -arg * else: * return arg # <<<<<<<<<<<<<< @@ -12552,7 +12610,7 @@ static Py_ssize_t abs_py_ssize_t(Py_ssize_t __pyx_v_arg) { goto __pyx_L0; } - /* "View.MemoryView":1105 + /* "View.MemoryView":1109 * * * cdef Py_ssize_t abs_py_ssize_t(Py_ssize_t arg) nogil: # <<<<<<<<<<<<<< @@ -12565,7 +12623,7 @@ static Py_ssize_t abs_py_ssize_t(Py_ssize_t __pyx_v_arg) { return __pyx_r; } -/* "View.MemoryView":1112 +/* "View.MemoryView":1116 * * @cname('__pyx_get_best_slice_order') * cdef char get_best_order(__Pyx_memviewslice *mslice, int ndim) nogil: # <<<<<<<<<<<<<< @@ -12583,7 +12641,7 @@ static char __pyx_get_best_slice_order(__Pyx_memviewslice *__pyx_v_mslice, int _ int __pyx_t_3; int __pyx_t_4; - /* "View.MemoryView":1117 + /* "View.MemoryView":1121 * """ * cdef int i * cdef Py_ssize_t c_stride = 0 # <<<<<<<<<<<<<< @@ -12592,7 +12650,7 @@ static char __pyx_get_best_slice_order(__Pyx_memviewslice *__pyx_v_mslice, int _ */ __pyx_v_c_stride = 0; - /* "View.MemoryView":1118 + /* "View.MemoryView":1122 * cdef int i * cdef Py_ssize_t c_stride = 0 * cdef Py_ssize_t f_stride = 0 # <<<<<<<<<<<<<< @@ -12601,7 +12659,7 @@ static char __pyx_get_best_slice_order(__Pyx_memviewslice *__pyx_v_mslice, int _ */ __pyx_v_f_stride = 0; - /* "View.MemoryView":1120 + /* "View.MemoryView":1124 * cdef Py_ssize_t f_stride = 0 * * for i in range(ndim - 1, -1, -1): # <<<<<<<<<<<<<< @@ -12611,7 +12669,7 @@ static char __pyx_get_best_slice_order(__Pyx_memviewslice *__pyx_v_mslice, int _ for (__pyx_t_1 = (__pyx_v_ndim - 1); __pyx_t_1 > -1; __pyx_t_1-=1) { __pyx_v_i = __pyx_t_1; - /* "View.MemoryView":1121 + /* "View.MemoryView":1125 * * for i in range(ndim - 1, -1, -1): * if mslice.shape[i] > 1: # <<<<<<<<<<<<<< @@ -12621,7 +12679,7 @@ static char __pyx_get_best_slice_order(__Pyx_memviewslice *__pyx_v_mslice, int _ __pyx_t_2 = (((__pyx_v_mslice->shape[__pyx_v_i]) > 1) != 0); if (__pyx_t_2) { - /* "View.MemoryView":1122 + /* "View.MemoryView":1126 * for i in range(ndim - 1, -1, -1): * if mslice.shape[i] > 1: * c_stride = mslice.strides[i] # <<<<<<<<<<<<<< @@ -12630,7 +12688,7 @@ static char __pyx_get_best_slice_order(__Pyx_memviewslice *__pyx_v_mslice, int _ */ __pyx_v_c_stride = (__pyx_v_mslice->strides[__pyx_v_i]); - /* "View.MemoryView":1123 + /* "View.MemoryView":1127 * if mslice.shape[i] > 1: * c_stride = mslice.strides[i] * break # <<<<<<<<<<<<<< @@ -12639,7 +12697,7 @@ static char __pyx_get_best_slice_order(__Pyx_memviewslice *__pyx_v_mslice, int _ */ goto __pyx_L4_break; - /* "View.MemoryView":1121 + /* "View.MemoryView":1125 * * for i in range(ndim - 1, -1, -1): * if mslice.shape[i] > 1: # <<<<<<<<<<<<<< @@ -12650,7 +12708,7 @@ static char __pyx_get_best_slice_order(__Pyx_memviewslice *__pyx_v_mslice, int _ } __pyx_L4_break:; - /* "View.MemoryView":1125 + /* "View.MemoryView":1129 * break * * for i in range(ndim): # <<<<<<<<<<<<<< @@ -12662,7 +12720,7 @@ static char __pyx_get_best_slice_order(__Pyx_memviewslice *__pyx_v_mslice, int _ for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { __pyx_v_i = __pyx_t_4; - /* "View.MemoryView":1126 + /* "View.MemoryView":1130 * * for i in range(ndim): * if mslice.shape[i] > 1: # <<<<<<<<<<<<<< @@ -12672,7 +12730,7 @@ static char __pyx_get_best_slice_order(__Pyx_memviewslice *__pyx_v_mslice, int _ __pyx_t_2 = (((__pyx_v_mslice->shape[__pyx_v_i]) > 1) != 0); if (__pyx_t_2) { - /* "View.MemoryView":1127 + /* "View.MemoryView":1131 * for i in range(ndim): * if mslice.shape[i] > 1: * f_stride = mslice.strides[i] # <<<<<<<<<<<<<< @@ -12681,7 +12739,7 @@ static char __pyx_get_best_slice_order(__Pyx_memviewslice *__pyx_v_mslice, int _ */ __pyx_v_f_stride = (__pyx_v_mslice->strides[__pyx_v_i]); - /* "View.MemoryView":1128 + /* "View.MemoryView":1132 * if mslice.shape[i] > 1: * f_stride = mslice.strides[i] * break # <<<<<<<<<<<<<< @@ -12690,7 +12748,7 @@ static char __pyx_get_best_slice_order(__Pyx_memviewslice *__pyx_v_mslice, int _ */ goto __pyx_L7_break; - /* "View.MemoryView":1126 + /* "View.MemoryView":1130 * * for i in range(ndim): * if mslice.shape[i] > 1: # <<<<<<<<<<<<<< @@ -12701,7 +12759,7 @@ static char __pyx_get_best_slice_order(__Pyx_memviewslice *__pyx_v_mslice, int _ } __pyx_L7_break:; - /* "View.MemoryView":1130 + /* "View.MemoryView":1134 * break * * if abs_py_ssize_t(c_stride) <= abs_py_ssize_t(f_stride): # <<<<<<<<<<<<<< @@ -12711,7 +12769,7 @@ static char __pyx_get_best_slice_order(__Pyx_memviewslice *__pyx_v_mslice, int _ __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":1131 + /* "View.MemoryView":1135 * * if abs_py_ssize_t(c_stride) <= abs_py_ssize_t(f_stride): * return 'C' # <<<<<<<<<<<<<< @@ -12721,7 +12779,7 @@ static char __pyx_get_best_slice_order(__Pyx_memviewslice *__pyx_v_mslice, int _ __pyx_r = 'C'; goto __pyx_L0; - /* "View.MemoryView":1130 + /* "View.MemoryView":1134 * break * * if abs_py_ssize_t(c_stride) <= abs_py_ssize_t(f_stride): # <<<<<<<<<<<<<< @@ -12730,7 +12788,7 @@ static char __pyx_get_best_slice_order(__Pyx_memviewslice *__pyx_v_mslice, int _ */ } - /* "View.MemoryView":1133 + /* "View.MemoryView":1137 * return 'C' * else: * return 'F' # <<<<<<<<<<<<<< @@ -12742,7 +12800,7 @@ static char __pyx_get_best_slice_order(__Pyx_memviewslice *__pyx_v_mslice, int _ goto __pyx_L0; } - /* "View.MemoryView":1112 + /* "View.MemoryView":1116 * * @cname('__pyx_get_best_slice_order') * cdef char get_best_order(__Pyx_memviewslice *mslice, int ndim) nogil: # <<<<<<<<<<<<<< @@ -12755,7 +12813,7 @@ static char __pyx_get_best_slice_order(__Pyx_memviewslice *__pyx_v_mslice, int _ return __pyx_r; } -/* "View.MemoryView":1136 +/* "View.MemoryView":1140 * * @cython.cdivision(True) * cdef void _copy_strided_to_strided(char *src_data, Py_ssize_t *src_strides, # <<<<<<<<<<<<<< @@ -12776,7 +12834,7 @@ static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v Py_ssize_t __pyx_t_5; Py_ssize_t __pyx_t_6; - /* "View.MemoryView":1143 + /* "View.MemoryView":1147 * * cdef Py_ssize_t i * cdef Py_ssize_t src_extent = src_shape[0] # <<<<<<<<<<<<<< @@ -12785,7 +12843,7 @@ static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v */ __pyx_v_src_extent = (__pyx_v_src_shape[0]); - /* "View.MemoryView":1144 + /* "View.MemoryView":1148 * cdef Py_ssize_t i * cdef Py_ssize_t src_extent = src_shape[0] * cdef Py_ssize_t dst_extent = dst_shape[0] # <<<<<<<<<<<<<< @@ -12794,7 +12852,7 @@ static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v */ __pyx_v_dst_extent = (__pyx_v_dst_shape[0]); - /* "View.MemoryView":1145 + /* "View.MemoryView":1149 * 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] # <<<<<<<<<<<<<< @@ -12803,7 +12861,7 @@ static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v */ __pyx_v_src_stride = (__pyx_v_src_strides[0]); - /* "View.MemoryView":1146 + /* "View.MemoryView":1150 * 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] # <<<<<<<<<<<<<< @@ -12812,7 +12870,7 @@ static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v */ __pyx_v_dst_stride = (__pyx_v_dst_strides[0]); - /* "View.MemoryView":1148 + /* "View.MemoryView":1152 * cdef Py_ssize_t dst_stride = dst_strides[0] * * if ndim == 1: # <<<<<<<<<<<<<< @@ -12822,7 +12880,7 @@ static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v __pyx_t_1 = ((__pyx_v_ndim == 1) != 0); if (__pyx_t_1) { - /* "View.MemoryView":1149 + /* "View.MemoryView":1153 * * if ndim == 1: * if (src_stride > 0 and dst_stride > 0 and # <<<<<<<<<<<<<< @@ -12842,7 +12900,7 @@ static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v goto __pyx_L5_bool_binop_done; } - /* "View.MemoryView":1150 + /* "View.MemoryView":1154 * if ndim == 1: * if (src_stride > 0 and dst_stride > 0 and * src_stride == itemsize == dst_stride): # <<<<<<<<<<<<<< @@ -12857,7 +12915,7 @@ static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v __pyx_t_1 = __pyx_t_3; __pyx_L5_bool_binop_done:; - /* "View.MemoryView":1149 + /* "View.MemoryView":1153 * * if ndim == 1: * if (src_stride > 0 and dst_stride > 0 and # <<<<<<<<<<<<<< @@ -12866,7 +12924,7 @@ static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v */ if (__pyx_t_1) { - /* "View.MemoryView":1151 + /* "View.MemoryView":1155 * if (src_stride > 0 and dst_stride > 0 and * src_stride == itemsize == dst_stride): * memcpy(dst_data, src_data, itemsize * dst_extent) # <<<<<<<<<<<<<< @@ -12875,7 +12933,7 @@ static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v */ (void)(memcpy(__pyx_v_dst_data, __pyx_v_src_data, (__pyx_v_itemsize * __pyx_v_dst_extent))); - /* "View.MemoryView":1149 + /* "View.MemoryView":1153 * * if ndim == 1: * if (src_stride > 0 and dst_stride > 0 and # <<<<<<<<<<<<<< @@ -12885,7 +12943,7 @@ static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v goto __pyx_L4; } - /* "View.MemoryView":1153 + /* "View.MemoryView":1157 * memcpy(dst_data, src_data, itemsize * dst_extent) * else: * for i in range(dst_extent): # <<<<<<<<<<<<<< @@ -12898,7 +12956,7 @@ static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) { __pyx_v_i = __pyx_t_6; - /* "View.MemoryView":1154 + /* "View.MemoryView":1158 * else: * for i in range(dst_extent): * memcpy(dst_data, src_data, itemsize) # <<<<<<<<<<<<<< @@ -12907,7 +12965,7 @@ static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v */ (void)(memcpy(__pyx_v_dst_data, __pyx_v_src_data, __pyx_v_itemsize)); - /* "View.MemoryView":1155 + /* "View.MemoryView":1159 * for i in range(dst_extent): * memcpy(dst_data, src_data, itemsize) * src_data += src_stride # <<<<<<<<<<<<<< @@ -12916,7 +12974,7 @@ static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v */ __pyx_v_src_data = (__pyx_v_src_data + __pyx_v_src_stride); - /* "View.MemoryView":1156 + /* "View.MemoryView":1160 * memcpy(dst_data, src_data, itemsize) * src_data += src_stride * dst_data += dst_stride # <<<<<<<<<<<<<< @@ -12928,7 +12986,7 @@ static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v } __pyx_L4:; - /* "View.MemoryView":1148 + /* "View.MemoryView":1152 * cdef Py_ssize_t dst_stride = dst_strides[0] * * if ndim == 1: # <<<<<<<<<<<<<< @@ -12938,7 +12996,7 @@ static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v goto __pyx_L3; } - /* "View.MemoryView":1158 + /* "View.MemoryView":1162 * dst_data += dst_stride * else: * for i in range(dst_extent): # <<<<<<<<<<<<<< @@ -12951,7 +13009,7 @@ static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) { __pyx_v_i = __pyx_t_6; - /* "View.MemoryView":1159 + /* "View.MemoryView":1163 * else: * for i in range(dst_extent): * _copy_strided_to_strided(src_data, src_strides + 1, # <<<<<<<<<<<<<< @@ -12960,7 +13018,7 @@ static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v */ _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":1163 + /* "View.MemoryView":1167 * src_shape + 1, dst_shape + 1, * ndim - 1, itemsize) * src_data += src_stride # <<<<<<<<<<<<<< @@ -12969,7 +13027,7 @@ static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v */ __pyx_v_src_data = (__pyx_v_src_data + __pyx_v_src_stride); - /* "View.MemoryView":1164 + /* "View.MemoryView":1168 * ndim - 1, itemsize) * src_data += src_stride * dst_data += dst_stride # <<<<<<<<<<<<<< @@ -12981,7 +13039,7 @@ static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v } __pyx_L3:; - /* "View.MemoryView":1136 + /* "View.MemoryView":1140 * * @cython.cdivision(True) * cdef void _copy_strided_to_strided(char *src_data, Py_ssize_t *src_strides, # <<<<<<<<<<<<<< @@ -12992,7 +13050,7 @@ static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v /* function exit code */ } -/* "View.MemoryView":1166 +/* "View.MemoryView":1170 * dst_data += dst_stride * * cdef void copy_strided_to_strided(__Pyx_memviewslice *src, # <<<<<<<<<<<<<< @@ -13002,7 +13060,7 @@ static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v 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":1169 + /* "View.MemoryView":1173 * __Pyx_memviewslice *dst, * int ndim, size_t itemsize) nogil: * _copy_strided_to_strided(src.data, src.strides, dst.data, dst.strides, # <<<<<<<<<<<<<< @@ -13011,7 +13069,7 @@ static void copy_strided_to_strided(__Pyx_memviewslice *__pyx_v_src, __Pyx_memvi */ _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":1166 + /* "View.MemoryView":1170 * dst_data += dst_stride * * cdef void copy_strided_to_strided(__Pyx_memviewslice *src, # <<<<<<<<<<<<<< @@ -13022,57 +13080,57 @@ static void copy_strided_to_strided(__Pyx_memviewslice *__pyx_v_src, __Pyx_memvi /* function exit code */ } -/* "View.MemoryView":1173 +/* "View.MemoryView":1177 * * @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 int i + * 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) { - int __pyx_v_i; + Py_ssize_t __pyx_v_shape; Py_ssize_t __pyx_v_size; Py_ssize_t __pyx_r; Py_ssize_t __pyx_t_1; - int __pyx_t_2; - int __pyx_t_3; - int __pyx_t_4; + Py_ssize_t *__pyx_t_2; + Py_ssize_t *__pyx_t_3; + Py_ssize_t *__pyx_t_4; - /* "View.MemoryView":1176 + /* "View.MemoryView":1179 + * 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 int i - * cdef Py_ssize_t size = src.memview.view.itemsize # <<<<<<<<<<<<<< + * cdef Py_ssize_t shape, size = src.memview.view.itemsize # <<<<<<<<<<<<<< * - * for i in range(ndim): + * for shape in src.shape[:ndim]: */ __pyx_t_1 = __pyx_v_src->memview->view.itemsize; __pyx_v_size = __pyx_t_1; - /* "View.MemoryView":1178 - * cdef Py_ssize_t size = src.memview.view.itemsize + /* "View.MemoryView":1181 + * cdef Py_ssize_t shape, size = src.memview.view.itemsize * - * for i in range(ndim): # <<<<<<<<<<<<<< - * size *= src.shape[i] + * for shape in src.shape[:ndim]: # <<<<<<<<<<<<<< + * size *= shape * */ - __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_i = __pyx_t_4; + __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":1179 + /* "View.MemoryView":1182 * - * for i in range(ndim): - * size *= src.shape[i] # <<<<<<<<<<<<<< + * for shape in src.shape[:ndim]: + * size *= shape # <<<<<<<<<<<<<< * * return size */ - __pyx_v_size = (__pyx_v_size * (__pyx_v_src->shape[__pyx_v_i])); + __pyx_v_size = (__pyx_v_size * __pyx_v_shape); } - /* "View.MemoryView":1181 - * size *= src.shape[i] + /* "View.MemoryView":1184 + * size *= shape * * return size # <<<<<<<<<<<<<< * @@ -13081,12 +13139,12 @@ static Py_ssize_t __pyx_memoryview_slice_get_size(__Pyx_memviewslice *__pyx_v_sr __pyx_r = __pyx_v_size; goto __pyx_L0; - /* "View.MemoryView":1173 + /* "View.MemoryView":1177 * * @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 int i + * cdef Py_ssize_t shape, size = src.memview.view.itemsize */ /* function exit code */ @@ -13094,7 +13152,7 @@ static Py_ssize_t __pyx_memoryview_slice_get_size(__Pyx_memviewslice *__pyx_v_sr return __pyx_r; } -/* "View.MemoryView":1184 +/* "View.MemoryView":1187 * * @cname('__pyx_fill_contig_strides_array') * cdef Py_ssize_t fill_contig_strides_array( # <<<<<<<<<<<<<< @@ -13110,7 +13168,7 @@ static Py_ssize_t __pyx_fill_contig_strides_array(Py_ssize_t *__pyx_v_shape, Py_ int __pyx_t_3; int __pyx_t_4; - /* "View.MemoryView":1193 + /* "View.MemoryView":1196 * cdef int idx * * if order == 'F': # <<<<<<<<<<<<<< @@ -13120,38 +13178,38 @@ static Py_ssize_t __pyx_fill_contig_strides_array(Py_ssize_t *__pyx_v_shape, Py_ __pyx_t_1 = ((__pyx_v_order == 'F') != 0); if (__pyx_t_1) { - /* "View.MemoryView":1194 + /* "View.MemoryView":1197 * * if order == 'F': * for idx in range(ndim): # <<<<<<<<<<<<<< * strides[idx] = stride - * stride = stride * shape[idx] + * 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":1195 + /* "View.MemoryView":1198 * if order == 'F': * for idx in range(ndim): * strides[idx] = stride # <<<<<<<<<<<<<< - * stride = stride * shape[idx] + * stride *= shape[idx] * else: */ (__pyx_v_strides[__pyx_v_idx]) = __pyx_v_stride; - /* "View.MemoryView":1196 + /* "View.MemoryView":1199 * for idx in range(ndim): * strides[idx] = stride - * stride = stride * shape[idx] # <<<<<<<<<<<<<< + * 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":1193 + /* "View.MemoryView":1196 * cdef int idx * * if order == 'F': # <<<<<<<<<<<<<< @@ -13161,30 +13219,30 @@ static Py_ssize_t __pyx_fill_contig_strides_array(Py_ssize_t *__pyx_v_shape, Py_ goto __pyx_L3; } - /* "View.MemoryView":1198 - * stride = stride * shape[idx] + /* "View.MemoryView":1201 + * stride *= shape[idx] * else: * for idx in range(ndim - 1, -1, -1): # <<<<<<<<<<<<<< * strides[idx] = stride - * stride = stride * shape[idx] + * 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":1199 + /* "View.MemoryView":1202 * else: * for idx in range(ndim - 1, -1, -1): * strides[idx] = stride # <<<<<<<<<<<<<< - * stride = stride * shape[idx] + * stride *= shape[idx] * */ (__pyx_v_strides[__pyx_v_idx]) = __pyx_v_stride; - /* "View.MemoryView":1200 + /* "View.MemoryView":1203 * for idx in range(ndim - 1, -1, -1): * strides[idx] = stride - * stride = stride * shape[idx] # <<<<<<<<<<<<<< + * stride *= shape[idx] # <<<<<<<<<<<<<< * * return stride */ @@ -13193,8 +13251,8 @@ static Py_ssize_t __pyx_fill_contig_strides_array(Py_ssize_t *__pyx_v_shape, Py_ } __pyx_L3:; - /* "View.MemoryView":1202 - * stride = stride * shape[idx] + /* "View.MemoryView":1205 + * stride *= shape[idx] * * return stride # <<<<<<<<<<<<<< * @@ -13203,7 +13261,7 @@ static Py_ssize_t __pyx_fill_contig_strides_array(Py_ssize_t *__pyx_v_shape, Py_ __pyx_r = __pyx_v_stride; goto __pyx_L0; - /* "View.MemoryView":1184 + /* "View.MemoryView":1187 * * @cname('__pyx_fill_contig_strides_array') * cdef Py_ssize_t fill_contig_strides_array( # <<<<<<<<<<<<<< @@ -13216,7 +13274,7 @@ static Py_ssize_t __pyx_fill_contig_strides_array(Py_ssize_t *__pyx_v_shape, Py_ return __pyx_r; } -/* "View.MemoryView":1205 +/* "View.MemoryView":1208 * * @cname('__pyx_memoryview_copy_data_to_temp') * cdef void *copy_data_to_temp(__Pyx_memviewslice *src, # <<<<<<<<<<<<<< @@ -13237,7 +13295,7 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, int __pyx_t_5; int __pyx_t_6; - /* "View.MemoryView":1216 + /* "View.MemoryView":1219 * cdef void *result * * cdef size_t itemsize = src.memview.view.itemsize # <<<<<<<<<<<<<< @@ -13247,7 +13305,7 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, __pyx_t_1 = __pyx_v_src->memview->view.itemsize; __pyx_v_itemsize = __pyx_t_1; - /* "View.MemoryView":1217 + /* "View.MemoryView":1220 * * cdef size_t itemsize = src.memview.view.itemsize * cdef size_t size = slice_get_size(src, ndim) # <<<<<<<<<<<<<< @@ -13256,7 +13314,7 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, */ __pyx_v_size = __pyx_memoryview_slice_get_size(__pyx_v_src, __pyx_v_ndim); - /* "View.MemoryView":1219 + /* "View.MemoryView":1222 * cdef size_t size = slice_get_size(src, ndim) * * result = malloc(size) # <<<<<<<<<<<<<< @@ -13265,7 +13323,7 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, */ __pyx_v_result = malloc(__pyx_v_size); - /* "View.MemoryView":1220 + /* "View.MemoryView":1223 * * result = malloc(size) * if not result: # <<<<<<<<<<<<<< @@ -13275,16 +13333,16 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, __pyx_t_2 = ((!(__pyx_v_result != 0)) != 0); if (__pyx_t_2) { - /* "View.MemoryView":1221 + /* "View.MemoryView":1224 * 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(1, 1221, __pyx_L1_error) + __pyx_t_3 = __pyx_memoryview_err(__pyx_builtin_MemoryError, NULL); if (unlikely(__pyx_t_3 == ((int)-1))) __PYX_ERR(1, 1224, __pyx_L1_error) - /* "View.MemoryView":1220 + /* "View.MemoryView":1223 * * result = malloc(size) * if not result: # <<<<<<<<<<<<<< @@ -13293,7 +13351,7 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, */ } - /* "View.MemoryView":1224 + /* "View.MemoryView":1227 * * * tmpslice.data = result # <<<<<<<<<<<<<< @@ -13302,7 +13360,7 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, */ __pyx_v_tmpslice->data = ((char *)__pyx_v_result); - /* "View.MemoryView":1225 + /* "View.MemoryView":1228 * * tmpslice.data = result * tmpslice.memview = src.memview # <<<<<<<<<<<<<< @@ -13312,7 +13370,7 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, __pyx_t_4 = __pyx_v_src->memview; __pyx_v_tmpslice->memview = __pyx_t_4; - /* "View.MemoryView":1226 + /* "View.MemoryView":1229 * tmpslice.data = result * tmpslice.memview = src.memview * for i in range(ndim): # <<<<<<<<<<<<<< @@ -13324,7 +13382,7 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) { __pyx_v_i = __pyx_t_6; - /* "View.MemoryView":1227 + /* "View.MemoryView":1230 * tmpslice.memview = src.memview * for i in range(ndim): * tmpslice.shape[i] = src.shape[i] # <<<<<<<<<<<<<< @@ -13333,7 +13391,7 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, */ (__pyx_v_tmpslice->shape[__pyx_v_i]) = (__pyx_v_src->shape[__pyx_v_i]); - /* "View.MemoryView":1228 + /* "View.MemoryView":1231 * for i in range(ndim): * tmpslice.shape[i] = src.shape[i] * tmpslice.suboffsets[i] = -1 # <<<<<<<<<<<<<< @@ -13343,7 +13401,7 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, (__pyx_v_tmpslice->suboffsets[__pyx_v_i]) = -1L; } - /* "View.MemoryView":1230 + /* "View.MemoryView":1233 * tmpslice.suboffsets[i] = -1 * * fill_contig_strides_array(&tmpslice.shape[0], &tmpslice.strides[0], itemsize, # <<<<<<<<<<<<<< @@ -13352,7 +13410,7 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, */ (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":1234 + /* "View.MemoryView":1237 * * * for i in range(ndim): # <<<<<<<<<<<<<< @@ -13364,7 +13422,7 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) { __pyx_v_i = __pyx_t_6; - /* "View.MemoryView":1235 + /* "View.MemoryView":1238 * * for i in range(ndim): * if tmpslice.shape[i] == 1: # <<<<<<<<<<<<<< @@ -13374,7 +13432,7 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, __pyx_t_2 = (((__pyx_v_tmpslice->shape[__pyx_v_i]) == 1) != 0); if (__pyx_t_2) { - /* "View.MemoryView":1236 + /* "View.MemoryView":1239 * for i in range(ndim): * if tmpslice.shape[i] == 1: * tmpslice.strides[i] = 0 # <<<<<<<<<<<<<< @@ -13383,7 +13441,7 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, */ (__pyx_v_tmpslice->strides[__pyx_v_i]) = 0; - /* "View.MemoryView":1235 + /* "View.MemoryView":1238 * * for i in range(ndim): * if tmpslice.shape[i] == 1: # <<<<<<<<<<<<<< @@ -13393,7 +13451,7 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, } } - /* "View.MemoryView":1238 + /* "View.MemoryView":1241 * tmpslice.strides[i] = 0 * * if slice_is_contig(src[0], order, ndim): # <<<<<<<<<<<<<< @@ -13403,7 +13461,7 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, __pyx_t_2 = (__pyx_memviewslice_is_contig((__pyx_v_src[0]), __pyx_v_order, __pyx_v_ndim) != 0); if (__pyx_t_2) { - /* "View.MemoryView":1239 + /* "View.MemoryView":1242 * * if slice_is_contig(src[0], order, ndim): * memcpy(result, src.data, size) # <<<<<<<<<<<<<< @@ -13412,7 +13470,7 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, */ (void)(memcpy(__pyx_v_result, __pyx_v_src->data, __pyx_v_size)); - /* "View.MemoryView":1238 + /* "View.MemoryView":1241 * tmpslice.strides[i] = 0 * * if slice_is_contig(src[0], order, ndim): # <<<<<<<<<<<<<< @@ -13422,7 +13480,7 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, goto __pyx_L9; } - /* "View.MemoryView":1241 + /* "View.MemoryView":1244 * memcpy(result, src.data, size) * else: * copy_strided_to_strided(src, tmpslice, ndim, itemsize) # <<<<<<<<<<<<<< @@ -13434,7 +13492,7 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, } __pyx_L9:; - /* "View.MemoryView":1243 + /* "View.MemoryView":1246 * copy_strided_to_strided(src, tmpslice, ndim, itemsize) * * return result # <<<<<<<<<<<<<< @@ -13444,7 +13502,7 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, __pyx_r = __pyx_v_result; goto __pyx_L0; - /* "View.MemoryView":1205 + /* "View.MemoryView":1208 * * @cname('__pyx_memoryview_copy_data_to_temp') * cdef void *copy_data_to_temp(__Pyx_memviewslice *src, # <<<<<<<<<<<<<< @@ -13468,7 +13526,7 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, return __pyx_r; } -/* "View.MemoryView":1248 +/* "View.MemoryView":1251 * * @cname('__pyx_memoryview_err_extents') * cdef int _err_extents(int i, Py_ssize_t extent1, # <<<<<<<<<<<<<< @@ -13488,20 +13546,20 @@ static int __pyx_memoryview_err_extents(int __pyx_v_i, Py_ssize_t __pyx_v_extent #endif __Pyx_RefNannySetupContext("_err_extents", 0); - /* "View.MemoryView":1251 + /* "View.MemoryView":1254 * 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(1, 1251, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_i); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 1254, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = PyInt_FromSsize_t(__pyx_v_extent1); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1251, __pyx_L1_error) + __pyx_t_2 = PyInt_FromSsize_t(__pyx_v_extent1); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1254, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyInt_FromSsize_t(__pyx_v_extent2); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 1251, __pyx_L1_error) + __pyx_t_3 = PyInt_FromSsize_t(__pyx_v_extent2); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 1254, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); - __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 1251, __pyx_L1_error) + __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 1254, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_GIVEREF(__pyx_t_1); PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1); @@ -13513,24 +13571,24 @@ static int __pyx_memoryview_err_extents(int __pyx_v_i, Py_ssize_t __pyx_v_extent __pyx_t_2 = 0; __pyx_t_3 = 0; - /* "View.MemoryView":1250 + /* "View.MemoryView":1253 * 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(1, 1250, __pyx_L1_error) + __pyx_t_3 = __Pyx_PyString_Format(__pyx_kp_s_got_differing_extents_in_dimensi, __pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 1253, __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(1, 1250, __pyx_L1_error) + __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_ValueError, __pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 1253, __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(1, 1250, __pyx_L1_error) + __PYX_ERR(1, 1253, __pyx_L1_error) - /* "View.MemoryView":1248 + /* "View.MemoryView":1251 * * @cname('__pyx_memoryview_err_extents') * cdef int _err_extents(int i, Py_ssize_t extent1, # <<<<<<<<<<<<<< @@ -13553,7 +13611,7 @@ static int __pyx_memoryview_err_extents(int __pyx_v_i, Py_ssize_t __pyx_v_extent return __pyx_r; } -/* "View.MemoryView":1254 +/* "View.MemoryView":1257 * * @cname('__pyx_memoryview_err_dim') * cdef int _err_dim(object error, char *msg, int dim) except -1 with gil: # <<<<<<<<<<<<<< @@ -13574,18 +13632,18 @@ static int __pyx_memoryview_err_dim(PyObject *__pyx_v_error, char *__pyx_v_msg, __Pyx_RefNannySetupContext("_err_dim", 0); __Pyx_INCREF(__pyx_v_error); - /* "View.MemoryView":1255 + /* "View.MemoryView":1258 * @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(1, 1255, __pyx_L1_error) + __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(1, 1258, __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(1, 1255, __pyx_L1_error) + __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_dim); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 1258, __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(1, 1255, __pyx_L1_error) + __pyx_t_4 = PyUnicode_Format(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 1258, __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; @@ -13603,14 +13661,14 @@ static int __pyx_memoryview_err_dim(PyObject *__pyx_v_error, char *__pyx_v_msg, __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(1, 1255, __pyx_L1_error) + if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 1258, __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(1, 1255, __pyx_L1_error) + __PYX_ERR(1, 1258, __pyx_L1_error) - /* "View.MemoryView":1254 + /* "View.MemoryView":1257 * * @cname('__pyx_memoryview_err_dim') * cdef int _err_dim(object error, char *msg, int dim) except -1 with gil: # <<<<<<<<<<<<<< @@ -13634,7 +13692,7 @@ static int __pyx_memoryview_err_dim(PyObject *__pyx_v_error, char *__pyx_v_msg, return __pyx_r; } -/* "View.MemoryView":1258 +/* "View.MemoryView":1261 * * @cname('__pyx_memoryview_err') * cdef int _err(object error, char *msg) except -1 with gil: # <<<<<<<<<<<<<< @@ -13656,7 +13714,7 @@ static int __pyx_memoryview_err(PyObject *__pyx_v_error, char *__pyx_v_msg) { __Pyx_RefNannySetupContext("_err", 0); __Pyx_INCREF(__pyx_v_error); - /* "View.MemoryView":1259 + /* "View.MemoryView":1262 * @cname('__pyx_memoryview_err') * cdef int _err(object error, char *msg) except -1 with gil: * if msg != NULL: # <<<<<<<<<<<<<< @@ -13666,14 +13724,14 @@ static int __pyx_memoryview_err(PyObject *__pyx_v_error, char *__pyx_v_msg) { __pyx_t_1 = ((__pyx_v_msg != NULL) != 0); if (unlikely(__pyx_t_1)) { - /* "View.MemoryView":1260 + /* "View.MemoryView":1263 * 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(1, 1260, __pyx_L1_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(1, 1263, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_INCREF(__pyx_v_error); __pyx_t_4 = __pyx_v_error; __pyx_t_5 = NULL; @@ -13689,14 +13747,14 @@ static int __pyx_memoryview_err(PyObject *__pyx_v_error, char *__pyx_v_msg) { __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(1, 1260, __pyx_L1_error) + if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1263, __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(1, 1260, __pyx_L1_error) + __PYX_ERR(1, 1263, __pyx_L1_error) - /* "View.MemoryView":1259 + /* "View.MemoryView":1262 * @cname('__pyx_memoryview_err') * cdef int _err(object error, char *msg) except -1 with gil: * if msg != NULL: # <<<<<<<<<<<<<< @@ -13705,7 +13763,7 @@ static int __pyx_memoryview_err(PyObject *__pyx_v_error, char *__pyx_v_msg) { */ } - /* "View.MemoryView":1262 + /* "View.MemoryView":1265 * raise error(msg.decode('ascii')) * else: * raise error # <<<<<<<<<<<<<< @@ -13714,10 +13772,10 @@ static int __pyx_memoryview_err(PyObject *__pyx_v_error, char *__pyx_v_msg) { */ /*else*/ { __Pyx_Raise(__pyx_v_error, 0, 0, 0); - __PYX_ERR(1, 1262, __pyx_L1_error) + __PYX_ERR(1, 1265, __pyx_L1_error) } - /* "View.MemoryView":1258 + /* "View.MemoryView":1261 * * @cname('__pyx_memoryview_err') * cdef int _err(object error, char *msg) except -1 with gil: # <<<<<<<<<<<<<< @@ -13741,7 +13799,7 @@ static int __pyx_memoryview_err(PyObject *__pyx_v_error, char *__pyx_v_msg) { return __pyx_r; } -/* "View.MemoryView":1265 +/* "View.MemoryView":1268 * * @cname('__pyx_memoryview_copy_contents') * cdef int memoryview_copy_contents(__Pyx_memviewslice src, # <<<<<<<<<<<<<< @@ -13768,7 +13826,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ void *__pyx_t_7; int __pyx_t_8; - /* "View.MemoryView":1273 + /* "View.MemoryView":1276 * Check for overlapping memory and verify the shapes. * """ * cdef void *tmpdata = NULL # <<<<<<<<<<<<<< @@ -13777,7 +13835,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ __pyx_v_tmpdata = NULL; - /* "View.MemoryView":1274 + /* "View.MemoryView":1277 * """ * cdef void *tmpdata = NULL * cdef size_t itemsize = src.memview.view.itemsize # <<<<<<<<<<<<<< @@ -13787,7 +13845,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ __pyx_t_1 = __pyx_v_src.memview->view.itemsize; __pyx_v_itemsize = __pyx_t_1; - /* "View.MemoryView":1276 + /* "View.MemoryView":1279 * cdef size_t itemsize = src.memview.view.itemsize * cdef int i * cdef char order = get_best_order(&src, src_ndim) # <<<<<<<<<<<<<< @@ -13796,7 +13854,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ __pyx_v_order = __pyx_get_best_slice_order((&__pyx_v_src), __pyx_v_src_ndim); - /* "View.MemoryView":1277 + /* "View.MemoryView":1280 * cdef int i * cdef char order = get_best_order(&src, src_ndim) * cdef bint broadcasting = False # <<<<<<<<<<<<<< @@ -13805,7 +13863,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ __pyx_v_broadcasting = 0; - /* "View.MemoryView":1278 + /* "View.MemoryView":1281 * cdef char order = get_best_order(&src, src_ndim) * cdef bint broadcasting = False * cdef bint direct_copy = False # <<<<<<<<<<<<<< @@ -13814,7 +13872,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ __pyx_v_direct_copy = 0; - /* "View.MemoryView":1281 + /* "View.MemoryView":1284 * cdef __Pyx_memviewslice tmp * * if src_ndim < dst_ndim: # <<<<<<<<<<<<<< @@ -13824,7 +13882,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ __pyx_t_2 = ((__pyx_v_src_ndim < __pyx_v_dst_ndim) != 0); if (__pyx_t_2) { - /* "View.MemoryView":1282 + /* "View.MemoryView":1285 * * if src_ndim < dst_ndim: * broadcast_leading(&src, src_ndim, dst_ndim) # <<<<<<<<<<<<<< @@ -13833,7 +13891,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ __pyx_memoryview_broadcast_leading((&__pyx_v_src), __pyx_v_src_ndim, __pyx_v_dst_ndim); - /* "View.MemoryView":1281 + /* "View.MemoryView":1284 * cdef __Pyx_memviewslice tmp * * if src_ndim < dst_ndim: # <<<<<<<<<<<<<< @@ -13843,7 +13901,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ goto __pyx_L3; } - /* "View.MemoryView":1283 + /* "View.MemoryView":1286 * if src_ndim < dst_ndim: * broadcast_leading(&src, src_ndim, dst_ndim) * elif dst_ndim < src_ndim: # <<<<<<<<<<<<<< @@ -13853,7 +13911,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ __pyx_t_2 = ((__pyx_v_dst_ndim < __pyx_v_src_ndim) != 0); if (__pyx_t_2) { - /* "View.MemoryView":1284 + /* "View.MemoryView":1287 * broadcast_leading(&src, src_ndim, dst_ndim) * elif dst_ndim < src_ndim: * broadcast_leading(&dst, dst_ndim, src_ndim) # <<<<<<<<<<<<<< @@ -13862,7 +13920,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ __pyx_memoryview_broadcast_leading((&__pyx_v_dst), __pyx_v_dst_ndim, __pyx_v_src_ndim); - /* "View.MemoryView":1283 + /* "View.MemoryView":1286 * if src_ndim < dst_ndim: * broadcast_leading(&src, src_ndim, dst_ndim) * elif dst_ndim < src_ndim: # <<<<<<<<<<<<<< @@ -13872,7 +13930,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ } __pyx_L3:; - /* "View.MemoryView":1286 + /* "View.MemoryView":1289 * broadcast_leading(&dst, dst_ndim, src_ndim) * * cdef int ndim = max(src_ndim, dst_ndim) # <<<<<<<<<<<<<< @@ -13888,7 +13946,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ } __pyx_v_ndim = __pyx_t_5; - /* "View.MemoryView":1288 + /* "View.MemoryView":1291 * cdef int ndim = max(src_ndim, dst_ndim) * * for i in range(ndim): # <<<<<<<<<<<<<< @@ -13900,7 +13958,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { __pyx_v_i = __pyx_t_4; - /* "View.MemoryView":1289 + /* "View.MemoryView":1292 * * for i in range(ndim): * if src.shape[i] != dst.shape[i]: # <<<<<<<<<<<<<< @@ -13910,7 +13968,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ __pyx_t_2 = (((__pyx_v_src.shape[__pyx_v_i]) != (__pyx_v_dst.shape[__pyx_v_i])) != 0); if (__pyx_t_2) { - /* "View.MemoryView":1290 + /* "View.MemoryView":1293 * for i in range(ndim): * if src.shape[i] != dst.shape[i]: * if src.shape[i] == 1: # <<<<<<<<<<<<<< @@ -13920,7 +13978,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ __pyx_t_2 = (((__pyx_v_src.shape[__pyx_v_i]) == 1) != 0); if (__pyx_t_2) { - /* "View.MemoryView":1291 + /* "View.MemoryView":1294 * if src.shape[i] != dst.shape[i]: * if src.shape[i] == 1: * broadcasting = True # <<<<<<<<<<<<<< @@ -13929,7 +13987,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ __pyx_v_broadcasting = 1; - /* "View.MemoryView":1292 + /* "View.MemoryView":1295 * if src.shape[i] == 1: * broadcasting = True * src.strides[i] = 0 # <<<<<<<<<<<<<< @@ -13938,7 +13996,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ (__pyx_v_src.strides[__pyx_v_i]) = 0; - /* "View.MemoryView":1290 + /* "View.MemoryView":1293 * for i in range(ndim): * if src.shape[i] != dst.shape[i]: * if src.shape[i] == 1: # <<<<<<<<<<<<<< @@ -13948,7 +14006,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ goto __pyx_L7; } - /* "View.MemoryView":1294 + /* "View.MemoryView":1297 * src.strides[i] = 0 * else: * _err_extents(i, dst.shape[i], src.shape[i]) # <<<<<<<<<<<<<< @@ -13956,11 +14014,11 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ * 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(1, 1294, __pyx_L1_error) + __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(1, 1297, __pyx_L1_error) } __pyx_L7:; - /* "View.MemoryView":1289 + /* "View.MemoryView":1292 * * for i in range(ndim): * if src.shape[i] != dst.shape[i]: # <<<<<<<<<<<<<< @@ -13969,7 +14027,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ } - /* "View.MemoryView":1296 + /* "View.MemoryView":1299 * _err_extents(i, dst.shape[i], src.shape[i]) * * if src.suboffsets[i] >= 0: # <<<<<<<<<<<<<< @@ -13979,16 +14037,16 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ __pyx_t_2 = (((__pyx_v_src.suboffsets[__pyx_v_i]) >= 0) != 0); if (__pyx_t_2) { - /* "View.MemoryView":1297 + /* "View.MemoryView":1300 * * 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(1, 1297, __pyx_L1_error) + __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(1, 1300, __pyx_L1_error) - /* "View.MemoryView":1296 + /* "View.MemoryView":1299 * _err_extents(i, dst.shape[i], src.shape[i]) * * if src.suboffsets[i] >= 0: # <<<<<<<<<<<<<< @@ -13998,7 +14056,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ } } - /* "View.MemoryView":1299 + /* "View.MemoryView":1302 * _err_dim(ValueError, "Dimension %d is not direct", i) * * if slices_overlap(&src, &dst, ndim, itemsize): # <<<<<<<<<<<<<< @@ -14008,7 +14066,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ __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":1301 + /* "View.MemoryView":1304 * if slices_overlap(&src, &dst, ndim, itemsize): * * if not slice_is_contig(src, order, ndim): # <<<<<<<<<<<<<< @@ -14018,7 +14076,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ __pyx_t_2 = ((!(__pyx_memviewslice_is_contig(__pyx_v_src, __pyx_v_order, __pyx_v_ndim) != 0)) != 0); if (__pyx_t_2) { - /* "View.MemoryView":1302 + /* "View.MemoryView":1305 * * if not slice_is_contig(src, order, ndim): * order = get_best_order(&dst, ndim) # <<<<<<<<<<<<<< @@ -14027,7 +14085,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ __pyx_v_order = __pyx_get_best_slice_order((&__pyx_v_dst), __pyx_v_ndim); - /* "View.MemoryView":1301 + /* "View.MemoryView":1304 * if slices_overlap(&src, &dst, ndim, itemsize): * * if not slice_is_contig(src, order, ndim): # <<<<<<<<<<<<<< @@ -14036,17 +14094,17 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ } - /* "View.MemoryView":1304 + /* "View.MemoryView":1307 * 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(1, 1304, __pyx_L1_error) + __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(1, 1307, __pyx_L1_error) __pyx_v_tmpdata = __pyx_t_7; - /* "View.MemoryView":1305 + /* "View.MemoryView":1308 * * tmpdata = copy_data_to_temp(&src, &tmp, order, ndim) * src = tmp # <<<<<<<<<<<<<< @@ -14055,7 +14113,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ __pyx_v_src = __pyx_v_tmp; - /* "View.MemoryView":1299 + /* "View.MemoryView":1302 * _err_dim(ValueError, "Dimension %d is not direct", i) * * if slices_overlap(&src, &dst, ndim, itemsize): # <<<<<<<<<<<<<< @@ -14064,7 +14122,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ } - /* "View.MemoryView":1307 + /* "View.MemoryView":1310 * src = tmp * * if not broadcasting: # <<<<<<<<<<<<<< @@ -14074,7 +14132,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ __pyx_t_2 = ((!(__pyx_v_broadcasting != 0)) != 0); if (__pyx_t_2) { - /* "View.MemoryView":1310 + /* "View.MemoryView":1313 * * * if slice_is_contig(src, 'C', ndim): # <<<<<<<<<<<<<< @@ -14084,7 +14142,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ __pyx_t_2 = (__pyx_memviewslice_is_contig(__pyx_v_src, 'C', __pyx_v_ndim) != 0); if (__pyx_t_2) { - /* "View.MemoryView":1311 + /* "View.MemoryView":1314 * * if slice_is_contig(src, 'C', ndim): * direct_copy = slice_is_contig(dst, 'C', ndim) # <<<<<<<<<<<<<< @@ -14093,7 +14151,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ __pyx_v_direct_copy = __pyx_memviewslice_is_contig(__pyx_v_dst, 'C', __pyx_v_ndim); - /* "View.MemoryView":1310 + /* "View.MemoryView":1313 * * * if slice_is_contig(src, 'C', ndim): # <<<<<<<<<<<<<< @@ -14103,7 +14161,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ goto __pyx_L12; } - /* "View.MemoryView":1312 + /* "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): # <<<<<<<<<<<<<< @@ -14113,7 +14171,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ __pyx_t_2 = (__pyx_memviewslice_is_contig(__pyx_v_src, 'F', __pyx_v_ndim) != 0); if (__pyx_t_2) { - /* "View.MemoryView":1313 + /* "View.MemoryView":1316 * direct_copy = slice_is_contig(dst, 'C', ndim) * elif slice_is_contig(src, 'F', ndim): * direct_copy = slice_is_contig(dst, 'F', ndim) # <<<<<<<<<<<<<< @@ -14122,7 +14180,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ __pyx_v_direct_copy = __pyx_memviewslice_is_contig(__pyx_v_dst, 'F', __pyx_v_ndim); - /* "View.MemoryView":1312 + /* "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): # <<<<<<<<<<<<<< @@ -14132,7 +14190,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ } __pyx_L12:; - /* "View.MemoryView":1315 + /* "View.MemoryView":1318 * direct_copy = slice_is_contig(dst, 'F', ndim) * * if direct_copy: # <<<<<<<<<<<<<< @@ -14142,7 +14200,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ __pyx_t_2 = (__pyx_v_direct_copy != 0); if (__pyx_t_2) { - /* "View.MemoryView":1317 + /* "View.MemoryView":1320 * if direct_copy: * * refcount_copying(&dst, dtype_is_object, ndim, False) # <<<<<<<<<<<<<< @@ -14151,7 +14209,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ __pyx_memoryview_refcount_copying((&__pyx_v_dst), __pyx_v_dtype_is_object, __pyx_v_ndim, 0); - /* "View.MemoryView":1318 + /* "View.MemoryView":1321 * * refcount_copying(&dst, dtype_is_object, ndim, False) * memcpy(dst.data, src.data, slice_get_size(&src, ndim)) # <<<<<<<<<<<<<< @@ -14160,7 +14218,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ (void)(memcpy(__pyx_v_dst.data, __pyx_v_src.data, __pyx_memoryview_slice_get_size((&__pyx_v_src), __pyx_v_ndim))); - /* "View.MemoryView":1319 + /* "View.MemoryView":1322 * 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) # <<<<<<<<<<<<<< @@ -14169,7 +14227,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ __pyx_memoryview_refcount_copying((&__pyx_v_dst), __pyx_v_dtype_is_object, __pyx_v_ndim, 1); - /* "View.MemoryView":1320 + /* "View.MemoryView":1323 * memcpy(dst.data, src.data, slice_get_size(&src, ndim)) * refcount_copying(&dst, dtype_is_object, ndim, True) * free(tmpdata) # <<<<<<<<<<<<<< @@ -14178,7 +14236,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ free(__pyx_v_tmpdata); - /* "View.MemoryView":1321 + /* "View.MemoryView":1324 * refcount_copying(&dst, dtype_is_object, ndim, True) * free(tmpdata) * return 0 # <<<<<<<<<<<<<< @@ -14188,7 +14246,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ __pyx_r = 0; goto __pyx_L0; - /* "View.MemoryView":1315 + /* "View.MemoryView":1318 * direct_copy = slice_is_contig(dst, 'F', ndim) * * if direct_copy: # <<<<<<<<<<<<<< @@ -14197,7 +14255,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ } - /* "View.MemoryView":1307 + /* "View.MemoryView":1310 * src = tmp * * if not broadcasting: # <<<<<<<<<<<<<< @@ -14206,7 +14264,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ } - /* "View.MemoryView":1323 + /* "View.MemoryView":1326 * return 0 * * if order == 'F' == get_best_order(&dst, ndim): # <<<<<<<<<<<<<< @@ -14220,25 +14278,25 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ __pyx_t_8 = (__pyx_t_2 != 0); if (__pyx_t_8) { - /* "View.MemoryView":1326 + /* "View.MemoryView":1329 * * * transpose_memslice(&src) # <<<<<<<<<<<<<< * transpose_memslice(&dst) * */ - __pyx_t_5 = __pyx_memslice_transpose((&__pyx_v_src)); if (unlikely(__pyx_t_5 == ((int)0))) __PYX_ERR(1, 1326, __pyx_L1_error) + __pyx_t_5 = __pyx_memslice_transpose((&__pyx_v_src)); if (unlikely(__pyx_t_5 == ((int)0))) __PYX_ERR(1, 1329, __pyx_L1_error) - /* "View.MemoryView":1327 + /* "View.MemoryView":1330 * * 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(1, 1327, __pyx_L1_error) + __pyx_t_5 = __pyx_memslice_transpose((&__pyx_v_dst)); if (unlikely(__pyx_t_5 == ((int)0))) __PYX_ERR(1, 1330, __pyx_L1_error) - /* "View.MemoryView":1323 + /* "View.MemoryView":1326 * return 0 * * if order == 'F' == get_best_order(&dst, ndim): # <<<<<<<<<<<<<< @@ -14247,7 +14305,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ } - /* "View.MemoryView":1329 + /* "View.MemoryView":1332 * transpose_memslice(&dst) * * refcount_copying(&dst, dtype_is_object, ndim, False) # <<<<<<<<<<<<<< @@ -14256,7 +14314,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ __pyx_memoryview_refcount_copying((&__pyx_v_dst), __pyx_v_dtype_is_object, __pyx_v_ndim, 0); - /* "View.MemoryView":1330 + /* "View.MemoryView":1333 * * refcount_copying(&dst, dtype_is_object, ndim, False) * copy_strided_to_strided(&src, &dst, ndim, itemsize) # <<<<<<<<<<<<<< @@ -14265,7 +14323,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ copy_strided_to_strided((&__pyx_v_src), (&__pyx_v_dst), __pyx_v_ndim, __pyx_v_itemsize); - /* "View.MemoryView":1331 + /* "View.MemoryView":1334 * refcount_copying(&dst, dtype_is_object, ndim, False) * copy_strided_to_strided(&src, &dst, ndim, itemsize) * refcount_copying(&dst, dtype_is_object, ndim, True) # <<<<<<<<<<<<<< @@ -14274,7 +14332,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ __pyx_memoryview_refcount_copying((&__pyx_v_dst), __pyx_v_dtype_is_object, __pyx_v_ndim, 1); - /* "View.MemoryView":1333 + /* "View.MemoryView":1336 * refcount_copying(&dst, dtype_is_object, ndim, True) * * free(tmpdata) # <<<<<<<<<<<<<< @@ -14283,7 +14341,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ */ free(__pyx_v_tmpdata); - /* "View.MemoryView":1334 + /* "View.MemoryView":1337 * * free(tmpdata) * return 0 # <<<<<<<<<<<<<< @@ -14293,7 +14351,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ __pyx_r = 0; goto __pyx_L0; - /* "View.MemoryView":1265 + /* "View.MemoryView":1268 * * @cname('__pyx_memoryview_copy_contents') * cdef int memoryview_copy_contents(__Pyx_memviewslice src, # <<<<<<<<<<<<<< @@ -14317,7 +14375,7 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_ return __pyx_r; } -/* "View.MemoryView":1337 +/* "View.MemoryView":1340 * * @cname('__pyx_memoryview_broadcast_leading') * cdef void broadcast_leading(__Pyx_memviewslice *mslice, # <<<<<<<<<<<<<< @@ -14332,7 +14390,7 @@ static void __pyx_memoryview_broadcast_leading(__Pyx_memviewslice *__pyx_v_mslic int __pyx_t_2; int __pyx_t_3; - /* "View.MemoryView":1341 + /* "View.MemoryView":1344 * int ndim_other) nogil: * cdef int i * cdef int offset = ndim_other - ndim # <<<<<<<<<<<<<< @@ -14341,7 +14399,7 @@ static void __pyx_memoryview_broadcast_leading(__Pyx_memviewslice *__pyx_v_mslic */ __pyx_v_offset = (__pyx_v_ndim_other - __pyx_v_ndim); - /* "View.MemoryView":1343 + /* "View.MemoryView":1346 * cdef int offset = ndim_other - ndim * * for i in range(ndim - 1, -1, -1): # <<<<<<<<<<<<<< @@ -14351,7 +14409,7 @@ static void __pyx_memoryview_broadcast_leading(__Pyx_memviewslice *__pyx_v_mslic for (__pyx_t_1 = (__pyx_v_ndim - 1); __pyx_t_1 > -1; __pyx_t_1-=1) { __pyx_v_i = __pyx_t_1; - /* "View.MemoryView":1344 + /* "View.MemoryView":1347 * * for i in range(ndim - 1, -1, -1): * mslice.shape[i + offset] = mslice.shape[i] # <<<<<<<<<<<<<< @@ -14360,7 +14418,7 @@ static void __pyx_memoryview_broadcast_leading(__Pyx_memviewslice *__pyx_v_mslic */ (__pyx_v_mslice->shape[(__pyx_v_i + __pyx_v_offset)]) = (__pyx_v_mslice->shape[__pyx_v_i]); - /* "View.MemoryView":1345 + /* "View.MemoryView":1348 * for i in range(ndim - 1, -1, -1): * mslice.shape[i + offset] = mslice.shape[i] * mslice.strides[i + offset] = mslice.strides[i] # <<<<<<<<<<<<<< @@ -14369,7 +14427,7 @@ static void __pyx_memoryview_broadcast_leading(__Pyx_memviewslice *__pyx_v_mslic */ (__pyx_v_mslice->strides[(__pyx_v_i + __pyx_v_offset)]) = (__pyx_v_mslice->strides[__pyx_v_i]); - /* "View.MemoryView":1346 + /* "View.MemoryView":1349 * mslice.shape[i + offset] = mslice.shape[i] * mslice.strides[i + offset] = mslice.strides[i] * mslice.suboffsets[i + offset] = mslice.suboffsets[i] # <<<<<<<<<<<<<< @@ -14379,7 +14437,7 @@ static void __pyx_memoryview_broadcast_leading(__Pyx_memviewslice *__pyx_v_mslic (__pyx_v_mslice->suboffsets[(__pyx_v_i + __pyx_v_offset)]) = (__pyx_v_mslice->suboffsets[__pyx_v_i]); } - /* "View.MemoryView":1348 + /* "View.MemoryView":1351 * mslice.suboffsets[i + offset] = mslice.suboffsets[i] * * for i in range(offset): # <<<<<<<<<<<<<< @@ -14391,7 +14449,7 @@ static void __pyx_memoryview_broadcast_leading(__Pyx_memviewslice *__pyx_v_mslic for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) { __pyx_v_i = __pyx_t_3; - /* "View.MemoryView":1349 + /* "View.MemoryView":1352 * * for i in range(offset): * mslice.shape[i] = 1 # <<<<<<<<<<<<<< @@ -14400,7 +14458,7 @@ static void __pyx_memoryview_broadcast_leading(__Pyx_memviewslice *__pyx_v_mslic */ (__pyx_v_mslice->shape[__pyx_v_i]) = 1; - /* "View.MemoryView":1350 + /* "View.MemoryView":1353 * for i in range(offset): * mslice.shape[i] = 1 * mslice.strides[i] = mslice.strides[0] # <<<<<<<<<<<<<< @@ -14409,7 +14467,7 @@ static void __pyx_memoryview_broadcast_leading(__Pyx_memviewslice *__pyx_v_mslic */ (__pyx_v_mslice->strides[__pyx_v_i]) = (__pyx_v_mslice->strides[0]); - /* "View.MemoryView":1351 + /* "View.MemoryView":1354 * mslice.shape[i] = 1 * mslice.strides[i] = mslice.strides[0] * mslice.suboffsets[i] = -1 # <<<<<<<<<<<<<< @@ -14419,7 +14477,7 @@ static void __pyx_memoryview_broadcast_leading(__Pyx_memviewslice *__pyx_v_mslic (__pyx_v_mslice->suboffsets[__pyx_v_i]) = -1L; } - /* "View.MemoryView":1337 + /* "View.MemoryView":1340 * * @cname('__pyx_memoryview_broadcast_leading') * cdef void broadcast_leading(__Pyx_memviewslice *mslice, # <<<<<<<<<<<<<< @@ -14430,7 +14488,7 @@ static void __pyx_memoryview_broadcast_leading(__Pyx_memviewslice *__pyx_v_mslic /* function exit code */ } -/* "View.MemoryView":1359 +/* "View.MemoryView":1362 * * @cname('__pyx_memoryview_refcount_copying') * cdef void refcount_copying(__Pyx_memviewslice *dst, bint dtype_is_object, # <<<<<<<<<<<<<< @@ -14441,7 +14499,7 @@ static void __pyx_memoryview_broadcast_leading(__Pyx_memviewslice *__pyx_v_mslic 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":1363 + /* "View.MemoryView":1366 * * * if dtype_is_object: # <<<<<<<<<<<<<< @@ -14451,7 +14509,7 @@ static void __pyx_memoryview_refcount_copying(__Pyx_memviewslice *__pyx_v_dst, i __pyx_t_1 = (__pyx_v_dtype_is_object != 0); if (__pyx_t_1) { - /* "View.MemoryView":1364 + /* "View.MemoryView":1367 * * if dtype_is_object: * refcount_objects_in_slice_with_gil(dst.data, dst.shape, # <<<<<<<<<<<<<< @@ -14460,7 +14518,7 @@ static void __pyx_memoryview_refcount_copying(__Pyx_memviewslice *__pyx_v_dst, i */ __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":1363 + /* "View.MemoryView":1366 * * * if dtype_is_object: # <<<<<<<<<<<<<< @@ -14469,7 +14527,7 @@ static void __pyx_memoryview_refcount_copying(__Pyx_memviewslice *__pyx_v_dst, i */ } - /* "View.MemoryView":1359 + /* "View.MemoryView":1362 * * @cname('__pyx_memoryview_refcount_copying') * cdef void refcount_copying(__Pyx_memviewslice *dst, bint dtype_is_object, # <<<<<<<<<<<<<< @@ -14480,7 +14538,7 @@ static void __pyx_memoryview_refcount_copying(__Pyx_memviewslice *__pyx_v_dst, i /* function exit code */ } -/* "View.MemoryView":1368 +/* "View.MemoryView":1371 * * @cname('__pyx_memoryview_refcount_objects_in_slice_with_gil') * cdef void refcount_objects_in_slice_with_gil(char *data, Py_ssize_t *shape, # <<<<<<<<<<<<<< @@ -14495,7 +14553,7 @@ static void __pyx_memoryview_refcount_objects_in_slice_with_gil(char *__pyx_v_da #endif __Pyx_RefNannySetupContext("refcount_objects_in_slice_with_gil", 0); - /* "View.MemoryView":1371 + /* "View.MemoryView":1374 * Py_ssize_t *strides, int ndim, * bint inc) with gil: * refcount_objects_in_slice(data, shape, strides, ndim, inc) # <<<<<<<<<<<<<< @@ -14504,7 +14562,7 @@ static void __pyx_memoryview_refcount_objects_in_slice_with_gil(char *__pyx_v_da */ __pyx_memoryview_refcount_objects_in_slice(__pyx_v_data, __pyx_v_shape, __pyx_v_strides, __pyx_v_ndim, __pyx_v_inc); - /* "View.MemoryView":1368 + /* "View.MemoryView":1371 * * @cname('__pyx_memoryview_refcount_objects_in_slice_with_gil') * cdef void refcount_objects_in_slice_with_gil(char *data, Py_ssize_t *shape, # <<<<<<<<<<<<<< @@ -14519,7 +14577,7 @@ static void __pyx_memoryview_refcount_objects_in_slice_with_gil(char *__pyx_v_da #endif } -/* "View.MemoryView":1374 +/* "View.MemoryView":1377 * * @cname('__pyx_memoryview_refcount_objects_in_slice') * cdef void refcount_objects_in_slice(char *data, Py_ssize_t *shape, # <<<<<<<<<<<<<< @@ -14536,7 +14594,7 @@ static void __pyx_memoryview_refcount_objects_in_slice(char *__pyx_v_data, Py_ss int __pyx_t_4; __Pyx_RefNannySetupContext("refcount_objects_in_slice", 0); - /* "View.MemoryView":1378 + /* "View.MemoryView":1381 * cdef Py_ssize_t i * * for i in range(shape[0]): # <<<<<<<<<<<<<< @@ -14548,7 +14606,7 @@ static void __pyx_memoryview_refcount_objects_in_slice(char *__pyx_v_data, Py_ss for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) { __pyx_v_i = __pyx_t_3; - /* "View.MemoryView":1379 + /* "View.MemoryView":1382 * * for i in range(shape[0]): * if ndim == 1: # <<<<<<<<<<<<<< @@ -14558,7 +14616,7 @@ static void __pyx_memoryview_refcount_objects_in_slice(char *__pyx_v_data, Py_ss __pyx_t_4 = ((__pyx_v_ndim == 1) != 0); if (__pyx_t_4) { - /* "View.MemoryView":1380 + /* "View.MemoryView":1383 * for i in range(shape[0]): * if ndim == 1: * if inc: # <<<<<<<<<<<<<< @@ -14568,7 +14626,7 @@ static void __pyx_memoryview_refcount_objects_in_slice(char *__pyx_v_data, Py_ss __pyx_t_4 = (__pyx_v_inc != 0); if (__pyx_t_4) { - /* "View.MemoryView":1381 + /* "View.MemoryView":1384 * if ndim == 1: * if inc: * Py_INCREF(( data)[0]) # <<<<<<<<<<<<<< @@ -14577,7 +14635,7 @@ static void __pyx_memoryview_refcount_objects_in_slice(char *__pyx_v_data, Py_ss */ Py_INCREF((((PyObject **)__pyx_v_data)[0])); - /* "View.MemoryView":1380 + /* "View.MemoryView":1383 * for i in range(shape[0]): * if ndim == 1: * if inc: # <<<<<<<<<<<<<< @@ -14587,7 +14645,7 @@ static void __pyx_memoryview_refcount_objects_in_slice(char *__pyx_v_data, Py_ss goto __pyx_L6; } - /* "View.MemoryView":1383 + /* "View.MemoryView":1386 * Py_INCREF(( data)[0]) * else: * Py_DECREF(( data)[0]) # <<<<<<<<<<<<<< @@ -14599,7 +14657,7 @@ static void __pyx_memoryview_refcount_objects_in_slice(char *__pyx_v_data, Py_ss } __pyx_L6:; - /* "View.MemoryView":1379 + /* "View.MemoryView":1382 * * for i in range(shape[0]): * if ndim == 1: # <<<<<<<<<<<<<< @@ -14609,7 +14667,7 @@ static void __pyx_memoryview_refcount_objects_in_slice(char *__pyx_v_data, Py_ss goto __pyx_L5; } - /* "View.MemoryView":1385 + /* "View.MemoryView":1388 * Py_DECREF(( data)[0]) * else: * refcount_objects_in_slice(data, shape + 1, strides + 1, # <<<<<<<<<<<<<< @@ -14618,7 +14676,7 @@ static void __pyx_memoryview_refcount_objects_in_slice(char *__pyx_v_data, Py_ss */ /*else*/ { - /* "View.MemoryView":1386 + /* "View.MemoryView":1389 * else: * refcount_objects_in_slice(data, shape + 1, strides + 1, * ndim - 1, inc) # <<<<<<<<<<<<<< @@ -14629,7 +14687,7 @@ static void __pyx_memoryview_refcount_objects_in_slice(char *__pyx_v_data, Py_ss } __pyx_L5:; - /* "View.MemoryView":1388 + /* "View.MemoryView":1391 * ndim - 1, inc) * * data += strides[0] # <<<<<<<<<<<<<< @@ -14639,7 +14697,7 @@ static void __pyx_memoryview_refcount_objects_in_slice(char *__pyx_v_data, Py_ss __pyx_v_data = (__pyx_v_data + (__pyx_v_strides[0])); } - /* "View.MemoryView":1374 + /* "View.MemoryView":1377 * * @cname('__pyx_memoryview_refcount_objects_in_slice') * cdef void refcount_objects_in_slice(char *data, Py_ssize_t *shape, # <<<<<<<<<<<<<< @@ -14651,7 +14709,7 @@ static void __pyx_memoryview_refcount_objects_in_slice(char *__pyx_v_data, Py_ss __Pyx_RefNannyFinishContext(); } -/* "View.MemoryView":1394 +/* "View.MemoryView":1397 * * @cname('__pyx_memoryview_slice_assign_scalar') * cdef void slice_assign_scalar(__Pyx_memviewslice *dst, int ndim, # <<<<<<<<<<<<<< @@ -14661,7 +14719,7 @@ static void __pyx_memoryview_refcount_objects_in_slice(char *__pyx_v_data, Py_ss 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":1397 + /* "View.MemoryView":1400 * size_t itemsize, void *item, * bint dtype_is_object) nogil: * refcount_copying(dst, dtype_is_object, ndim, False) # <<<<<<<<<<<<<< @@ -14670,7 +14728,7 @@ static void __pyx_memoryview_slice_assign_scalar(__Pyx_memviewslice *__pyx_v_dst */ __pyx_memoryview_refcount_copying(__pyx_v_dst, __pyx_v_dtype_is_object, __pyx_v_ndim, 0); - /* "View.MemoryView":1398 + /* "View.MemoryView":1401 * bint dtype_is_object) nogil: * refcount_copying(dst, dtype_is_object, ndim, False) * _slice_assign_scalar(dst.data, dst.shape, dst.strides, ndim, # <<<<<<<<<<<<<< @@ -14679,7 +14737,7 @@ static void __pyx_memoryview_slice_assign_scalar(__Pyx_memviewslice *__pyx_v_dst */ __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":1400 + /* "View.MemoryView":1403 * _slice_assign_scalar(dst.data, dst.shape, dst.strides, ndim, * itemsize, item) * refcount_copying(dst, dtype_is_object, ndim, True) # <<<<<<<<<<<<<< @@ -14688,7 +14746,7 @@ static void __pyx_memoryview_slice_assign_scalar(__Pyx_memviewslice *__pyx_v_dst */ __pyx_memoryview_refcount_copying(__pyx_v_dst, __pyx_v_dtype_is_object, __pyx_v_ndim, 1); - /* "View.MemoryView":1394 + /* "View.MemoryView":1397 * * @cname('__pyx_memoryview_slice_assign_scalar') * cdef void slice_assign_scalar(__Pyx_memviewslice *dst, int ndim, # <<<<<<<<<<<<<< @@ -14699,7 +14757,7 @@ static void __pyx_memoryview_slice_assign_scalar(__Pyx_memviewslice *__pyx_v_dst /* function exit code */ } -/* "View.MemoryView":1404 +/* "View.MemoryView":1407 * * @cname('__pyx_memoryview__slice_assign_scalar') * cdef void _slice_assign_scalar(char *data, Py_ssize_t *shape, # <<<<<<<<<<<<<< @@ -14716,7 +14774,7 @@ static void __pyx_memoryview__slice_assign_scalar(char *__pyx_v_data, Py_ssize_t Py_ssize_t __pyx_t_3; Py_ssize_t __pyx_t_4; - /* "View.MemoryView":1408 + /* "View.MemoryView":1411 * size_t itemsize, void *item) nogil: * cdef Py_ssize_t i * cdef Py_ssize_t stride = strides[0] # <<<<<<<<<<<<<< @@ -14725,7 +14783,7 @@ static void __pyx_memoryview__slice_assign_scalar(char *__pyx_v_data, Py_ssize_t */ __pyx_v_stride = (__pyx_v_strides[0]); - /* "View.MemoryView":1409 + /* "View.MemoryView":1412 * cdef Py_ssize_t i * cdef Py_ssize_t stride = strides[0] * cdef Py_ssize_t extent = shape[0] # <<<<<<<<<<<<<< @@ -14734,7 +14792,7 @@ static void __pyx_memoryview__slice_assign_scalar(char *__pyx_v_data, Py_ssize_t */ __pyx_v_extent = (__pyx_v_shape[0]); - /* "View.MemoryView":1411 + /* "View.MemoryView":1414 * cdef Py_ssize_t extent = shape[0] * * if ndim == 1: # <<<<<<<<<<<<<< @@ -14744,7 +14802,7 @@ static void __pyx_memoryview__slice_assign_scalar(char *__pyx_v_data, Py_ssize_t __pyx_t_1 = ((__pyx_v_ndim == 1) != 0); if (__pyx_t_1) { - /* "View.MemoryView":1412 + /* "View.MemoryView":1415 * * if ndim == 1: * for i in range(extent): # <<<<<<<<<<<<<< @@ -14756,7 +14814,7 @@ static void __pyx_memoryview__slice_assign_scalar(char *__pyx_v_data, Py_ssize_t for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { __pyx_v_i = __pyx_t_4; - /* "View.MemoryView":1413 + /* "View.MemoryView":1416 * if ndim == 1: * for i in range(extent): * memcpy(data, item, itemsize) # <<<<<<<<<<<<<< @@ -14765,7 +14823,7 @@ static void __pyx_memoryview__slice_assign_scalar(char *__pyx_v_data, Py_ssize_t */ (void)(memcpy(__pyx_v_data, __pyx_v_item, __pyx_v_itemsize)); - /* "View.MemoryView":1414 + /* "View.MemoryView":1417 * for i in range(extent): * memcpy(data, item, itemsize) * data += stride # <<<<<<<<<<<<<< @@ -14775,7 +14833,7 @@ static void __pyx_memoryview__slice_assign_scalar(char *__pyx_v_data, Py_ssize_t __pyx_v_data = (__pyx_v_data + __pyx_v_stride); } - /* "View.MemoryView":1411 + /* "View.MemoryView":1414 * cdef Py_ssize_t extent = shape[0] * * if ndim == 1: # <<<<<<<<<<<<<< @@ -14785,7 +14843,7 @@ static void __pyx_memoryview__slice_assign_scalar(char *__pyx_v_data, Py_ssize_t goto __pyx_L3; } - /* "View.MemoryView":1416 + /* "View.MemoryView":1419 * data += stride * else: * for i in range(extent): # <<<<<<<<<<<<<< @@ -14798,7 +14856,7 @@ static void __pyx_memoryview__slice_assign_scalar(char *__pyx_v_data, Py_ssize_t for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { __pyx_v_i = __pyx_t_4; - /* "View.MemoryView":1417 + /* "View.MemoryView":1420 * else: * for i in range(extent): * _slice_assign_scalar(data, shape + 1, strides + 1, # <<<<<<<<<<<<<< @@ -14807,7 +14865,7 @@ static void __pyx_memoryview__slice_assign_scalar(char *__pyx_v_data, Py_ssize_t */ __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":1419 + /* "View.MemoryView":1422 * _slice_assign_scalar(data, shape + 1, strides + 1, * ndim - 1, itemsize, item) * data += stride # <<<<<<<<<<<<<< @@ -14819,7 +14877,7 @@ static void __pyx_memoryview__slice_assign_scalar(char *__pyx_v_data, Py_ssize_t } __pyx_L3:; - /* "View.MemoryView":1404 + /* "View.MemoryView":1407 * * @cname('__pyx_memoryview__slice_assign_scalar') * cdef void _slice_assign_scalar(char *data, Py_ssize_t *shape, # <<<<<<<<<<<<<< @@ -15344,7 +15402,12 @@ static PyTypeObject __pyx_type___pyx_array = { 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 @@ -15394,6 +15457,12 @@ static PyTypeObject __pyx_type___pyx_array = { #if PY_VERSION_HEX >= 0x030400a1 0, /*tp_finalize*/ #endif + #if PY_VERSION_HEX >= 0x030800b1 + 0, /*tp_vectorcall*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 + 0, /*tp_print*/ + #endif }; static PyObject *__pyx_tp_new_Enum(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) { @@ -15452,7 +15521,12 @@ static PyTypeObject __pyx_type___pyx_MemviewEnum = { 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 @@ -15502,6 +15576,12 @@ static PyTypeObject __pyx_type___pyx_MemviewEnum = { #if PY_VERSION_HEX >= 0x030400a1 0, /*tp_finalize*/ #endif + #if PY_VERSION_HEX >= 0x030800b1 + 0, /*tp_vectorcall*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 + 0, /*tp_print*/ + #endif }; static struct __pyx_vtabstruct_memoryview __pyx_vtable_memoryview; @@ -15702,7 +15782,12 @@ static PyTypeObject __pyx_type___pyx_memoryview = { 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 @@ -15752,6 +15837,12 @@ static PyTypeObject __pyx_type___pyx_memoryview = { #if PY_VERSION_HEX >= 0x030400a1 0, /*tp_finalize*/ #endif + #if PY_VERSION_HEX >= 0x030800b1 + 0, /*tp_vectorcall*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 + 0, /*tp_print*/ + #endif }; static struct __pyx_vtabstruct__memoryviewslice __pyx_vtable__memoryviewslice; @@ -15829,7 +15920,12 @@ static PyTypeObject __pyx_type___pyx_memoryviewslice = { 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 @@ -15887,6 +15983,12 @@ static PyTypeObject __pyx_type___pyx_memoryviewslice = { #if PY_VERSION_HEX >= 0x030400a1 0, /*tp_finalize*/ #endif + #if PY_VERSION_HEX >= 0x030800b1 + 0, /*tp_vectorcall*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 + 0, /*tp_print*/ + #endif }; static PyMethodDef __pyx_methods[] = { @@ -16036,9 +16138,9 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { __pyx_builtin_MemoryError = __Pyx_GetBuiltinName(__pyx_n_s_MemoryError); if (!__pyx_builtin_MemoryError) __PYX_ERR(1, 148, __pyx_L1_error) __pyx_builtin_enumerate = __Pyx_GetBuiltinName(__pyx_n_s_enumerate); if (!__pyx_builtin_enumerate) __PYX_ERR(1, 151, __pyx_L1_error) __pyx_builtin_TypeError = __Pyx_GetBuiltinName(__pyx_n_s_TypeError); if (!__pyx_builtin_TypeError) __PYX_ERR(1, 2, __pyx_L1_error) - __pyx_builtin_Ellipsis = __Pyx_GetBuiltinName(__pyx_n_s_Ellipsis); if (!__pyx_builtin_Ellipsis) __PYX_ERR(1, 400, __pyx_L1_error) - __pyx_builtin_id = __Pyx_GetBuiltinName(__pyx_n_s_id); if (!__pyx_builtin_id) __PYX_ERR(1, 609, __pyx_L1_error) - __pyx_builtin_IndexError = __Pyx_GetBuiltinName(__pyx_n_s_IndexError); if (!__pyx_builtin_IndexError) __PYX_ERR(1, 828, __pyx_L1_error) + __pyx_builtin_Ellipsis = __Pyx_GetBuiltinName(__pyx_n_s_Ellipsis); if (!__pyx_builtin_Ellipsis) __PYX_ERR(1, 404, __pyx_L1_error) + __pyx_builtin_id = __Pyx_GetBuiltinName(__pyx_n_s_id); if (!__pyx_builtin_id) __PYX_ERR(1, 613, __pyx_L1_error) + __pyx_builtin_IndexError = __Pyx_GetBuiltinName(__pyx_n_s_IndexError); if (!__pyx_builtin_IndexError) __PYX_ERR(1, 832, __pyx_L1_error) return 0; __pyx_L1_error:; return -1; @@ -16122,58 +16224,58 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { __Pyx_GOTREF(__pyx_tuple__7); __Pyx_GIVEREF(__pyx_tuple__7); - /* "View.MemoryView":414 + /* "View.MemoryView":418 * 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__8 = PyTuple_Pack(1, __pyx_kp_s_Cannot_assign_to_read_only_memor); if (unlikely(!__pyx_tuple__8)) __PYX_ERR(1, 414, __pyx_L1_error) + __pyx_tuple__8 = PyTuple_Pack(1, __pyx_kp_s_Cannot_assign_to_read_only_memor); if (unlikely(!__pyx_tuple__8)) __PYX_ERR(1, 418, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__8); __Pyx_GIVEREF(__pyx_tuple__8); - /* "View.MemoryView":491 + /* "View.MemoryView":495 * 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__9 = PyTuple_Pack(1, __pyx_kp_s_Unable_to_convert_item_to_object); if (unlikely(!__pyx_tuple__9)) __PYX_ERR(1, 491, __pyx_L1_error) + __pyx_tuple__9 = PyTuple_Pack(1, __pyx_kp_s_Unable_to_convert_item_to_object); if (unlikely(!__pyx_tuple__9)) __PYX_ERR(1, 495, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__9); __Pyx_GIVEREF(__pyx_tuple__9); - /* "View.MemoryView":516 + /* "View.MemoryView":520 * 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__10 = PyTuple_Pack(1, __pyx_kp_s_Cannot_create_writable_memory_vi); if (unlikely(!__pyx_tuple__10)) __PYX_ERR(1, 516, __pyx_L1_error) + __pyx_tuple__10 = PyTuple_Pack(1, __pyx_kp_s_Cannot_create_writable_memory_vi); if (unlikely(!__pyx_tuple__10)) __PYX_ERR(1, 520, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__10); __Pyx_GIVEREF(__pyx_tuple__10); - /* "View.MemoryView":566 + /* "View.MemoryView":570 * 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__11 = PyTuple_Pack(1, __pyx_kp_s_Buffer_view_does_not_expose_stri); if (unlikely(!__pyx_tuple__11)) __PYX_ERR(1, 566, __pyx_L1_error) + __pyx_tuple__11 = PyTuple_Pack(1, __pyx_kp_s_Buffer_view_does_not_expose_stri); if (unlikely(!__pyx_tuple__11)) __PYX_ERR(1, 570, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__11); __Pyx_GIVEREF(__pyx_tuple__11); - /* "View.MemoryView":573 + /* "View.MemoryView":577 * 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__12 = PyTuple_New(1); if (unlikely(!__pyx_tuple__12)) __PYX_ERR(1, 573, __pyx_L1_error) + __pyx_tuple__12 = PyTuple_New(1); if (unlikely(!__pyx_tuple__12)) __PYX_ERR(1, 577, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__12); __Pyx_INCREF(__pyx_int_neg_1); __Pyx_GIVEREF(__pyx_int_neg_1); @@ -16199,25 +16301,25 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { __Pyx_GOTREF(__pyx_tuple__14); __Pyx_GIVEREF(__pyx_tuple__14); - /* "View.MemoryView":678 + /* "View.MemoryView":682 * if item is Ellipsis: * if not seen_ellipsis: * result.extend([slice(None)] * (ndim - len(tup) + 1)) # <<<<<<<<<<<<<< * seen_ellipsis = True * else: */ - __pyx_slice__15 = PySlice_New(Py_None, Py_None, Py_None); if (unlikely(!__pyx_slice__15)) __PYX_ERR(1, 678, __pyx_L1_error) + __pyx_slice__15 = PySlice_New(Py_None, Py_None, Py_None); if (unlikely(!__pyx_slice__15)) __PYX_ERR(1, 682, __pyx_L1_error) __Pyx_GOTREF(__pyx_slice__15); __Pyx_GIVEREF(__pyx_slice__15); - /* "View.MemoryView":699 + /* "View.MemoryView":703 * for suboffset in suboffsets[:ndim]: * if suboffset >= 0: * raise ValueError("Indirect dimensions not supported") # <<<<<<<<<<<<<< * * */ - __pyx_tuple__16 = PyTuple_Pack(1, __pyx_kp_s_Indirect_dimensions_not_supporte); if (unlikely(!__pyx_tuple__16)) __PYX_ERR(1, 699, __pyx_L1_error) + __pyx_tuple__16 = PyTuple_Pack(1, __pyx_kp_s_Indirect_dimensions_not_supporte); if (unlikely(!__pyx_tuple__16)) __PYX_ERR(1, 703, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__16); __Pyx_GIVEREF(__pyx_tuple__16); @@ -16366,12 +16468,16 @@ static int __Pyx_modinit_type_init_code(void) { __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(1, 105, __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(1, 105, __pyx_L1_error) if (__Pyx_setup_reduce((PyObject*)&__pyx_type___pyx_array) < 0) __PYX_ERR(1, 105, __pyx_L1_error) __pyx_array_type = &__pyx_type___pyx_array; if (PyType_Ready(&__pyx_type___pyx_MemviewEnum) < 0) __PYX_ERR(1, 279, __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; } @@ -16386,7 +16492,9 @@ static int __Pyx_modinit_type_init_code(void) { __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(1, 330, __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; } @@ -16398,13 +16506,15 @@ static int __Pyx_modinit_type_init_code(void) { __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(1, 961, __pyx_L1_error) + if (PyType_Ready(&__pyx_type___pyx_memoryviewslice) < 0) __PYX_ERR(1, 965, __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(1, 961, __pyx_L1_error) - if (__Pyx_setup_reduce((PyObject*)&__pyx_type___pyx_memoryviewslice) < 0) __PYX_ERR(1, 961, __pyx_L1_error) + if (__Pyx_SetVtable(__pyx_type___pyx_memoryviewslice.tp_dict, __pyx_vtabptr__memoryviewslice) < 0) __PYX_ERR(1, 965, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject*)&__pyx_type___pyx_memoryviewslice) < 0) __PYX_ERR(1, 965, __pyx_L1_error) __pyx_memoryviewslice_type = &__pyx_type___pyx_memoryviewslice; __Pyx_RefNannyFinishContext(); return 0; @@ -16598,10 +16708,9 @@ if (!__Pyx_RefNanny) { __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) - __pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error) - #if CYTHON_COMPILING_IN_PYPY Py_INCREF(__pyx_b); - #endif + __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) @@ -16620,9 +16729,9 @@ if (!__Pyx_RefNanny) { } #endif /*--- Builtin init code ---*/ - if (__Pyx_InitCachedBuiltins() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + if (__Pyx_InitCachedBuiltins() < 0) goto __pyx_L1_error; /*--- Constants init code ---*/ - if (__Pyx_InitCachedConstants() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + if (__Pyx_InitCachedConstants() < 0) goto __pyx_L1_error; /*--- Global type/function init code ---*/ (void)__Pyx_modinit_global_init_code(); (void)__Pyx_modinit_variable_export_code(); @@ -16755,29 +16864,29 @@ if (!__Pyx_RefNanny) { __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":545 + /* "View.MemoryView":549 * 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(1, 545, __pyx_L1_error) + __pyx_t_1 = __pyx_capsule_create(((void *)(&__pyx_memoryview_getbuffer)), ((char *)"getbuffer(obj, view, flags)")); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 549, __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(1, 545, __pyx_L1_error) + if (PyDict_SetItem((PyObject *)__pyx_memoryview_type->tp_dict, __pyx_n_s_pyx_getbuffer, __pyx_t_1) < 0) __PYX_ERR(1, 549, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; PyType_Modified(__pyx_memoryview_type); - /* "View.MemoryView":991 + /* "View.MemoryView":995 * 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(1, 991, __pyx_L1_error) + __pyx_t_1 = __pyx_capsule_create(((void *)(&__pyx_memoryview_getbuffer)), ((char *)"getbuffer(obj, view, flags)")); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 995, __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(1, 991, __pyx_L1_error) + if (PyDict_SetItem((PyObject *)__pyx_memoryviewslice_type->tp_dict, __pyx_n_s_pyx_getbuffer, __pyx_t_1) < 0) __PYX_ERR(1, 995, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; PyType_Modified(__pyx_memoryviewslice_type); @@ -17027,11 +17136,7 @@ __Pyx_init_memviewslice(struct __pyx_memoryview_obj *memview, int i, retval=-1; Py_buffer *buf = &memview->view; __Pyx_RefNannySetupContext("init_memviewslice", 0); - if (!buf) { - PyErr_SetString(PyExc_ValueError, - "buf is NULL."); - goto fail; - } else if (memviewslice->memview || memviewslice->data) { + if (memviewslice->memview || memviewslice->data) { PyErr_SetString(PyExc_ValueError, "memviewslice is already initialized!"); goto fail; @@ -17432,7 +17537,7 @@ static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args return result; } #if 1 || PY_VERSION_HEX < 0x030600B1 -static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, int nargs, PyObject *kwargs) { +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); @@ -17503,12 +17608,12 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, } #if PY_MAJOR_VERSION >= 3 result = PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL, - args, nargs, + args, (int)nargs, k, (int)nk, d, (int)nd, kwdefs, closure); #else result = PyEval_EvalCodeEx(co, globals, (PyObject *)NULL, - args, nargs, + args, (int)nargs, k, (int)nk, d, (int)nd, closure); #endif @@ -17968,6 +18073,32 @@ static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *o, PyObject *n, PyObject return (likely(r)) ? r : __Pyx_GetAttr3Default(d); } +/* 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) @@ -18496,48 +18627,6 @@ static CYTHON_INLINE long __Pyx_div_long(long a, long b) { return q; } -/* WriteUnraisableException */ -static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno, - CYTHON_UNUSED int lineno, CYTHON_UNUSED const char *filename, - int full_traceback, CYTHON_UNUSED int nogil) { - PyObject *old_exc, *old_val, *old_tb; - PyObject *ctx; - __Pyx_PyThreadState_declare -#ifdef WITH_THREAD - PyGILState_STATE state; - if (nogil) - state = PyGILState_Ensure(); -#ifdef _MSC_VER - else state = (PyGILState_STATE)-1; -#endif -#endif - __Pyx_PyThreadState_assign - __Pyx_ErrFetch(&old_exc, &old_val, &old_tb); - if (full_traceback) { - Py_XINCREF(old_exc); - Py_XINCREF(old_val); - Py_XINCREF(old_tb); - __Pyx_ErrRestore(old_exc, old_val, old_tb); - PyErr_PrintEx(1); - } - #if PY_MAJOR_VERSION < 3 - ctx = PyString_FromString(name); - #else - ctx = PyUnicode_FromString(name); - #endif - __Pyx_ErrRestore(old_exc, old_val, old_tb); - if (!ctx) { - PyErr_WriteUnraisable(Py_None); - } else { - PyErr_WriteUnraisable(ctx); - Py_DECREF(ctx); - } -#ifdef WITH_THREAD - if (nogil) - PyGILState_Release(state); -#endif -} - /* ImportFrom */ static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name) { PyObject* value = __Pyx_PyObject_GetAttrStr(module, name); @@ -18665,43 +18754,43 @@ static int __Pyx_setup_reduce(PyObject* type_obj) { PyObject *setstate = NULL; PyObject *setstate_cython = NULL; #if CYTHON_USE_PYTYPE_LOOKUP - if (_PyType_Lookup((PyTypeObject*)type_obj, __pyx_n_s_getstate)) goto GOOD; + if (_PyType_Lookup((PyTypeObject*)type_obj, __pyx_n_s_getstate)) goto __PYX_GOOD; #else - if (PyObject_HasAttr(type_obj, __pyx_n_s_getstate)) goto GOOD; + if (PyObject_HasAttr(type_obj, __pyx_n_s_getstate)) goto __PYX_GOOD; #endif #if CYTHON_USE_PYTYPE_LOOKUP - object_reduce_ex = _PyType_Lookup(&PyBaseObject_Type, __pyx_n_s_reduce_ex); if (!object_reduce_ex) goto BAD; + 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 BAD; + 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 BAD; + 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 BAD; + 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 BAD; + 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 BAD; + 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_GetAttrStr(type_obj, __pyx_n_s_reduce_cython); if (unlikely(!reduce_cython)) goto BAD; - ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_reduce, reduce_cython); if (unlikely(ret < 0)) goto BAD; - ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_reduce_cython); if (unlikely(ret < 0)) goto BAD; + reduce_cython = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_reduce_cython); if (unlikely(!reduce_cython)) goto __PYX_BAD; + 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; 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_GetAttrStr(type_obj, __pyx_n_s_setstate_cython); if (unlikely(!setstate_cython)) goto BAD; - ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_setstate, setstate_cython); if (unlikely(ret < 0)) goto BAD; - ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_setstate_cython); if (unlikely(ret < 0)) goto BAD; + setstate_cython = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_setstate_cython); if (unlikely(!setstate_cython)) goto __PYX_BAD; + 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; } PyType_Modified((PyTypeObject*)type_obj); } } - goto GOOD; -BAD: + 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; -GOOD: +__PYX_GOOD: #if !CYTHON_USE_PYTYPE_LOOKUP Py_XDECREF(object_reduce); Py_XDECREF(object_reduce_ex); @@ -18716,7 +18805,7 @@ static int __Pyx_setup_reduce(PyObject* type_obj) { /* CLineInTraceback */ #ifndef CYTHON_CLINE_IN_TRACEBACK -static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line) { +static int __Pyx_CLineForTraceback(CYTHON_NCP_UNUSED PyThreadState *tstate, int c_line) { PyObject *use_cline; PyObject *ptype, *pvalue, *ptraceback; #if CYTHON_COMPILING_IN_CPYTHON @@ -18820,7 +18909,7 @@ static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { 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)); + __pyx_code_cache.entries, ((size_t)new_max) * sizeof(__Pyx_CodeObjectCacheEntry)); if (unlikely(!entries)) { return; } @@ -19082,7 +19171,7 @@ static int __Pyx_BufFmt_ParseNumber(const char** ts) { return -1; } else { count = *t++ - '0'; - while (*t >= '0' && *t < '9') { + while (*t >= '0' && *t <= '9') { count *= 10; count += *t++ - '0'; } @@ -19103,6 +19192,7 @@ static void __Pyx_BufFmt_RaiseUnexpectedChar(char 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'"; @@ -19145,7 +19235,7 @@ static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) { } static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) { switch (ch) { - case 'c': case 'b': case 'B': case 's': case 'p': return 1; + 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); @@ -19229,7 +19319,7 @@ static char __Pyx_BufFmt_TypeCharToGroup(char ch, int is_complex) { case 'b': case 'h': case 'i': case 'l': case 'q': case 's': case 'p': return 'I'; - case 'B': case 'H': case 'I': case 'L': case 'Q': + case '?': case 'B': case 'H': case 'I': case 'L': case 'Q': return 'U'; case 'f': case 'd': case 'g': return (is_complex ? 'C' : 'R'); @@ -19508,7 +19598,7 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha return NULL; } CYTHON_FALLTHROUGH; - case 'c': case 'b': case 'B': case 'h': case 'H': case 'i': case 'I': + 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': @@ -19656,7 +19746,7 @@ __pyx_check_suboffsets(Py_buffer *buf, int dim, CYTHON_UNUSED int ndim, int spec } } if (spec & __Pyx_MEMVIEW_PTR) { - if (!buf->suboffsets || (buf->suboffsets && buf->suboffsets[dim] < 0)) { + if (!buf->suboffsets || (buf->suboffsets[dim] < 0)) { PyErr_Format(PyExc_ValueError, "Buffer is not indirectly accessible " "in dimension %d.", dim); diff --git a/openmmtools/multistate/multistateanalyzer.py b/openmmtools/multistate/multistateanalyzer.py index 7a3a1e040..7bb7b6c5f 100644 --- a/openmmtools/multistate/multistateanalyzer.py +++ b/openmmtools/multistate/multistateanalyzer.py @@ -31,7 +31,7 @@ import numpy as np from simtk import openmm import simtk.unit as units -from scipy.misc import logsumexp +from scipy.special import logsumexp from pymbar import MBAR, timeseries from openmmtools import multistate, utils, forces @@ -1067,7 +1067,7 @@ def _combine_phases(self, other, operator='+'): # Reset self._sign self._sign = '+' if self.name is None: - names.append(utils.generate_phase_name(self.name, [])) + names.append(multistate.utils.generate_phase_name(self.name, [])) else: names.append(self.name) if isinstance(other, MultiPhaseAnalyzer): @@ -1077,7 +1077,7 @@ def _combine_phases(self, other, operator='+'): final_new_names = [] for name in new_names: other_names = [n for n in new_names if n != name] - final_new_names.append(utils.generate_phase_name(name, other_names + names)) + final_new_names.append(multistate.utils.generate_phase_name(name, other_names + names)) names.extend(final_new_names) for new_sign in new_signs: if operator != '+' and new_sign == '+': @@ -1086,7 +1086,7 @@ def _combine_phases(self, other, operator='+'): signs.append('+') phases.extend(new_phases) elif isinstance(other, PhaseAnalyzer): - names.append(utils.generate_phase_name(other.name, names)) + names.append(multistate.utils.generate_phase_name(other.name, names)) if operator != '+' and other._sign == '+': signs.append('-') else: @@ -1170,9 +1170,9 @@ class MultiStateSamplerAnalyzer(PhaseAnalyzer): def __init__(self, *args, unbias_restraint=True, restraint_energy_cutoff='auto', restraint_distance_cutoff='auto', **kwargs): + # Warn that API is experimental - import warnings - warnings.warn('Warning: The openmmtools.multistate API is experimental and may change in future releases') + logger.warn('Warning: The openmmtools.multistate API is experimental and may change in future releases') # super() calls clear() that initialize the cached variables. super().__init__(*args, **kwargs) @@ -1688,11 +1688,19 @@ def extract_decorrelated(cached_dict, dtype, unit): restraint_force = copy.deepcopy(restraint_force) is_periodic = restraint_force.usesPeriodicBoundaryConditions() - # Store the original indices of the restrained atoms. - original_restrained_atom_indices1 = restraint_force.restrained_atom_indices1 - original_restrained_atom_indices2 = restraint_force.restrained_atom_indices2 - original_restrained_atom_indices = (original_restrained_atom_indices1 + - original_restrained_atom_indices2) + # Store the indices of the restrained atoms in the reduced system. + analysis_indices = self._reporter.analysis_particle_indices + + mapped_restrained_indices1 = restraint_force.restrained_atom_indices1 + mapped_restrained_indices2 = restraint_force.restrained_atom_indices2 + + mapped_restrained_indices1 = [analysis_indices.index(index) + for index in mapped_restrained_indices1] + mapped_restrained_indices2 = [analysis_indices.index(index) + for index in mapped_restrained_indices2] + + mapped_restrained_indices = (mapped_restrained_indices1 + + mapped_restrained_indices2) # Create new system with only solute and restraint forces. reduced_system = openmm.System() @@ -1745,7 +1753,7 @@ def extract_decorrelated(cached_dict, dtype, unit): analysis_particles_only=True) for replica_idx, sampler_state in enumerate(sampler_states): - sliced_sampler_state = sampler_state[original_restrained_atom_indices] + sliced_sampler_state = sampler_state[mapped_restrained_indices] sliced_sampler_state.apply_to_context(context) potential_energy = context.getState(getEnergy=True).getPotentialEnergy() self._restraint_energies[iteration][replica_idx] = potential_energy / _OPENMM_ENERGY_UNIT @@ -1762,11 +1770,11 @@ def extract_decorrelated(cached_dict, dtype, unit): dtype=np.float32) trajectory.image_molecules(inplace=True, anchor_molecules=anchor_molecules, other_molecules=imaged_molecules) - positions_group1 = trajectory.xyz[0][original_restrained_atom_indices1] - positions_group2 = trajectory.xyz[0][original_restrained_atom_indices2] + positions_group1 = trajectory.xyz[0][mapped_restrained_indices1] + positions_group2 = trajectory.xyz[0][mapped_restrained_indices2] else: - positions_group1 = sampler_state.positions[original_restrained_atom_indices1] - positions_group2 = sampler_state.positions[original_restrained_atom_indices2] + positions_group1 = sampler_state.positions[mapped_restrained_indices1] + positions_group2 = sampler_state.positions[mapped_restrained_indices2] positions_group1 /= _MDTRAJ_DISTANCE_UNIT positions_group2 /= _MDTRAJ_DISTANCE_UNIT diff --git a/openmmtools/multistate/multistatereporter.py b/openmmtools/multistate/multistatereporter.py index 72cfb8000..fb6dc8423 100644 --- a/openmmtools/multistate/multistatereporter.py +++ b/openmmtools/multistate/multistatereporter.py @@ -34,8 +34,8 @@ import time import uuid import yaml -import logging import warnings +import logging import collections import numpy as np @@ -46,7 +46,7 @@ from simtk import unit from openmmtools.utils import deserialize, with_timer, serialize, quantity_from_string -from openmmtools import version,states +from openmmtools import states logger = logging.getLogger(__name__) @@ -112,9 +112,8 @@ def __init__(self, storage, open_mode=None, analysis_particle_indices=()): # Warn that API is experimental - import warnings - warnings.warn('Warning: The openmmtools.multistate API is experimental and may change in future releases') - + logger.warn('Warning: The openmmtools.multistate API is experimental and may change in future releases') + # Handle checkpointing if type(checkpoint_interval) != int: raise ValueError("checkpoint_interval must be an integer!") @@ -372,9 +371,13 @@ def _open_dataset_robustly(self, *args, n_attempts=5, sleep_time=2, raise e except: logger.debug('Attempt {}/{} to open {} failed. Retrying ' - 'in {} seconds'.format(i+1, n_attempts, sleep_time)) + 'in {} seconds'.format(attempt+1, n_attempts, sleep_time)) time.sleep(sleep_time) + # At the very last attempt, we try setting the environment variable + # controlling the locking mechanism of HDF5 (see choderalab/yank#1165). + if n_attempts > 1: + os.environ['HDF5_USE_FILE_LOCKING'] = 'FALSE' # Last attempt finally raises any error. return netcdf.Dataset(*args, **kwargs) @@ -385,6 +388,8 @@ def _initialize_storage_file(self, ncfile, nc_name, convention): If the dataset has been initialized before, nothing happens. Return True if the file has been initialized before and False otherwise. """ + from openmmtools import __version__ + if 'scalar' not in ncfile.dimensions: # Create common dimensions. ncfile.createDimension('scalar', 1) # Scalar dimension. @@ -394,7 +399,7 @@ def _initialize_storage_file(self, ncfile, nc_name, convention): # Set global attributes. ncfile.application = 'YANK' ncfile.program = 'yank.py' - ncfile.programVersion = version.short_version + ncfile.programVersion = __version__ ncfile.Conventions = convention ncfile.ConventionVersion = '0.2' ncfile.DataUsedFor = nc_name @@ -727,12 +732,13 @@ def write_replica_thermodynamic_states(self, state_indices, iteration): self._ensure_dimension_exists('replica', n_replicas) # Create variables and attach units and description. - ncvar_states = self._storage_analysis.createVariable('states', 'i4', ('iteration', 'replica'), - zlib=False, - chunksizes=(self._checkpoint_interval, n_replicas)) - setattr(ncvar_states, 'units', 'none') - setattr(ncvar_states, "long_name", ("states[iteration][replica] is the thermodynamic state index " - "(0..n_states-1) of replica 'replica' of iteration 'iteration'.")) + ncvar_states = self._storage_analysis.createVariable( + 'states', 'i4', ('iteration', 'replica'), + zlib=False, chunksizes=(1, n_replicas) + ) + ncvar_states.units = 'none' + ncvar_states.long_name = ("states[iteration][replica] is the thermodynamic state index " + "(0..n_states-1) of replica 'replica' of iteration 'iteration'.") # Store thermodynamic states indices. self._storage_analysis.variables['states'][iteration, :] = state_indices[:] @@ -831,29 +837,23 @@ def write_energies(self, energy_thermodynamic_states, energy_neighborhoods, ener self._ensure_dimension_exists('replica', n_replicas) self._ensure_dimension_exists('state', n_states) if 'energies' not in self._storage_analysis.variables: - ncvar_energies = self._storage_analysis.createVariable('energies', - 'f8', - ('iteration', 'replica', 'state'), - zlib=False, - chunksizes=(self._checkpoint_interval, - n_replicas, - n_states)) + ncvar_energies = self._storage_analysis.createVariable( + 'energies', 'f8', ('iteration', 'replica', 'state'), + zlib=False, chunksizes=(1, n_replicas, n_states) + ) ncvar_energies.units = 'kT' ncvar_energies.long_name = ("energies[iteration][replica][state] is the reduced (unitless) " "energy of replica 'replica' from iteration 'iteration' evaluated " "at the thermodynamic state 'state'.") if 'neighborhoods' not in self._storage_analysis.variables: - ncvar_neighborhoods = self._storage_analysis.createVariable('neighborhoods', - 'i1', - ('iteration', 'replica', 'state'), - zlib=False, - fill_value=1, # old-style files will be upgraded to have all states - chunksizes=(self._checkpoint_interval, - n_replicas, - n_states)) - ncvar_neighborhoods.long_name = ("neighborhoods[iteration][replica][state] is 1 if this energy was computed " - "during this iteration.") + ncvar_neighborhoods = self._storage_analysis.createVariable( + 'neighborhoods', 'i1', ('iteration', 'replica', 'state'), + zlib=False, fill_value=1, # old-style files will be upgraded to have all states + chunksizes=(1, n_replicas, n_states) + ) + ncvar_neighborhoods.long_name = ("neighborhoods[iteration][replica][state] is 1 if " + "this energy was computed during this iteration.") if 'unsampled_energies' not in self._storage_analysis.variables: # Check if we have unsampled states. @@ -864,14 +864,10 @@ def write_energies(self, energy_thermodynamic_states, energy_neighborhoods, ener if 'unsampled_energies' not in self._storage_analysis.variables: # Create variable for thermodynamic state energies with units and descriptions. - ncvar_unsampled = self._storage_analysis.createVariable('unsampled_energies', - 'f8', - ('iteration', 'replica', 'unsampled'), - zlib=False, - chunksizes=(self._checkpoint_interval, - n_replicas, - n_unsampled_states) - ) + ncvar_unsampled = self._storage_analysis.createVariable( + 'unsampled_energies', 'f8', ('iteration', 'replica', 'unsampled'), + zlib=False, chunksizes=(1, n_replicas, n_unsampled_states) + ) ncvar_unsampled.units = 'kT' ncvar_unsampled.long_name = ("unsampled_energies[iteration][replica][state] is the reduced " "(unitless) energy of replica 'replica' from iteration 'iteration' " @@ -934,28 +930,20 @@ def write_mixing_statistics(self, n_accepted_matrix, n_proposed_matrix, iteratio self._ensure_dimension_exists('state', n_states) # Create variables with units and descriptions. - ncvar_accepted = self._storage_analysis.createVariable('accepted', - 'i4', - ('iteration', 'state', 'state'), - zlib=False, - chunksizes=(self._checkpoint_interval, - n_states, - n_states) - ) - ncvar_proposed = self._storage_analysis.createVariable('proposed', - 'i4', - ('iteration', 'state', 'state'), - zlib=False, - chunksizes=(self._checkpoint_interval, - n_states, - n_states) - ) - setattr(ncvar_accepted, 'units', 'none') - setattr(ncvar_proposed, 'units', 'none') - setattr(ncvar_accepted, 'long_name', ("accepted[iteration][i][j] is the number of proposed transitions " - "between states i and j from iteration 'iteration-1'.")) - setattr(ncvar_proposed, 'long_name', ("proposed[iteration][i][j] is the number of proposed transitions " - "between states i and j from iteration 'iteration-1'.")) + ncvar_accepted = self._storage_analysis.createVariable( + 'accepted', 'i4', ('iteration', 'state', 'state'), + zlib=False, chunksizes=(1, n_states, n_states) + ) + ncvar_proposed = self._storage_analysis.createVariable( + 'proposed', 'i4', ('iteration', 'state', 'state'), + zlib=False, chunksizes=(1, n_states, n_states) + ) + ncvar_accepted.units = 'none' + ncvar_proposed.units = 'none' + ncvar_accepted.long_name = ("accepted[iteration][i][j] is the number of proposed transitions " + "between states i and j from iteration 'iteration-1'.") + ncvar_proposed.long_name = ("proposed[iteration][i][j] is the number of proposed transitions " + "between states i and j from iteration 'iteration-1'.") # Store statistics. self._storage_analysis.variables['accepted'][iteration, :, :] = n_accepted_matrix[:, :] @@ -994,9 +982,8 @@ def write_timestamp(self, iteration: int): # Create variable if needed. for storage_key, storage in self._storage_dict.items(): if 'timestamp' not in storage.variables: - timestamp = storage.createVariable('timestamp', str, ('iteration',), - zlib=False, - chunksizes=(self._storage_chunks[storage_key],)) + storage.createVariable('timestamp', str, ('iteration',), + zlib=False, chunksizes=(1,)) timestamp = time.ctime() self._storage_analysis.variables['timestamp'][iteration] = timestamp @@ -1325,10 +1312,10 @@ def _write_1d_online_data(self, iteration, variable, data, storage): if variable not in storage.variables: variable_parameters = self._determine_netcdf_variable_parameters(iteration, data, storage) logger.debug('Creating new NetCDF variable %s with parameters: %s' % (variable, variable_parameters)) # DEBUG - nc_var = storage.createVariable(variable, variable_parameters['dtype'], - dimensions=variable_parameters['dims'], - chunksizes=variable_parameters['chunksizes'], - zlib=False) + storage.createVariable(variable, variable_parameters['dtype'], + dimensions=variable_parameters['dims'], + chunksizes=variable_parameters['chunksizes'], + zlib=False) # Get the variable nc_var = storage[variable] @@ -1395,7 +1382,7 @@ def _determine_netcdf_variable_parameters(self, iteration, data, storage): if iteration is not None: dims = ("iteration", data_dim) - chunks = (self._checkpoint_interval, size) + chunks = (1, size) else: dims = (data_dim,) chunks = (size,) @@ -1530,7 +1517,7 @@ def _ensure_group_exists_and_get(self, group_name, storage=None): return storage.groups[group_name] @staticmethod - def _initialize_sampler_variables_on_file(dataset, n_atoms, n_replicas, is_periodic, iteration_chunk=1): + def _initialize_sampler_variables_on_file(dataset, n_atoms, n_replicas, is_periodic): """ Initialize the NetCDF variables on the storage file needed to store sampler states. Does nothing if file already initialized @@ -1545,8 +1532,6 @@ def _initialize_sampler_variables_on_file(dataset, n_atoms, n_replicas, is_perio Number of Sampler states which will be written is_periodic : bool True if system is periodic; False otherwise. - iteration_chunk : int, Optional, Default: 1 - What chunksize to use for the iteration dimension """ if 'positions' not in dataset.variables: @@ -1555,31 +1540,30 @@ def _initialize_sampler_variables_on_file(dataset, n_atoms, n_replicas, is_perio if 'replica' not in dataset.dimensions: dataset.createDimension('replica', n_replicas) - # Define position variables + # Define position variables. ncvar_positions = dataset.createVariable('positions', 'f4', ('iteration', 'replica', 'atom', 'spatial'), - zlib=True, chunksizes=(iteration_chunk, n_replicas, n_atoms, 3)) - setattr(ncvar_positions, 'units', 'nm') - setattr(ncvar_positions, "long_name", ("positions[iteration][replica][atom][spatial] is position of " - "coordinate 'spatial' of atom 'atom' from replica 'replica' for " - "iteration 'iteration'.")) + zlib=True, chunksizes=(1, n_replicas, n_atoms, 3)) + ncvar_positions.units = 'nm' + ncvar_positions.long_name = ("positions[iteration][replica][atom][spatial] is position of " + "coordinate 'spatial' of atom 'atom' from replica 'replica' for " + "iteration 'iteration'.") # Define variables for periodic systems if is_periodic: ncvar_box_vectors = dataset.createVariable('box_vectors', 'f4', ('iteration', 'replica', 'spatial', 'spatial'), - zlib=False, chunksizes=(iteration_chunk, n_replicas, 3, 3)) + zlib=False, chunksizes=(1, n_replicas, 3, 3)) ncvar_volumes = dataset.createVariable('volumes', 'f8', ('iteration', 'replica'), - zlib=False, chunksizes=(iteration_chunk, n_replicas)) - - setattr(ncvar_box_vectors, 'units', 'nm') - setattr(ncvar_volumes, 'units', 'nm**3') + zlib=False, chunksizes=(1, n_replicas)) - setattr(ncvar_box_vectors, "long_name", ("box_vectors[iteration][replica][i][j] is dimension j of box " - "vector i for replica 'replica' from iteration " - "'iteration-1'.")) - setattr(ncvar_volumes, "long_name", ("volume[iteration][replica] is the box volume for replica " - "'replica' from iteration 'iteration-1'.")) + ncvar_box_vectors.units = 'nm' + ncvar_volumes.units = 'nm**3' + ncvar_box_vectors.long_name = ("box_vectors[iteration][replica][i][j] is dimension j of box " + "vector i for replica 'replica' from iteration " + "'iteration-1'.") + ncvar_volumes.long_name = ("volume[iteration][replica] is the box volume for replica " + "'replica' from iteration 'iteration-1'.") def _write_sampler_states_to_given_file(self, sampler_states: list, iteration: int, storage_file='checkpoint', obey_checkpoint_interval=True): @@ -1606,8 +1590,7 @@ def _write_sampler_states_to_given_file(self, sampler_states: list, iteration: i n_particles = sampler_states[0].n_particles n_replicas = len(sampler_states) self._initialize_sampler_variables_on_file(storage, n_particles, - n_replicas, is_periodic, - iteration_chunk=self._storage_chunks[storage_file]) + n_replicas, is_periodic) if obey_checkpoint_interval: write_iteration = self._calculate_checkpoint_iteration(iteration) else: @@ -1763,11 +1746,6 @@ def _write_dict(self, path, data, storage_name='analysis', packed_data[0] = data_str nc_variable[:] = packed_data - @ property - def _storage_chunks(self): - """Known NetCDF storage chunk sizes""" - return {'checkpoint': 1, 'analysis': self._checkpoint_interval} - # ============================================================================== # MODULE INTERNAL USAGE UTILITIES diff --git a/openmmtools/multistate/multistatesampler.py b/openmmtools/multistate/multistatesampler.py index c333ac0b6..7228176eb 100644 --- a/openmmtools/multistate/multistatesampler.py +++ b/openmmtools/multistate/multistatesampler.py @@ -141,8 +141,7 @@ def __init__(self, mcmc_moves=None, number_of_iterations=1, locality=None): # Warn that API is experimental - import warnings - warnings.warn('Warning: The openmmtools.multistate API is experimental and may change in future releases') + logger.warn('Warning: The openmmtools.multistate API is experimental and may change in future releases') # These will be set on initialization. See function # create() for explanation of single variables. @@ -1200,9 +1199,7 @@ def _propagate_replicas(self): # Update all sampler states. For non-0 nodes, this will update only the # sampler states associated to the replicas propagated by this node. for replica_id, propagated_state in zip(replica_ids, propagated_states): - propagated_positions, propagated_box_vectors = propagated_state # Unpack. - self._sampler_states[replica_id].positions = propagated_positions - self._sampler_states[replica_id].box_vectors = propagated_box_vectors + self._sampler_states[replica_id].__setstate__(propagated_state, ignore_velocities=True) # Gather all MCMCMoves statistics. All nodes must have these up-to-date # since they are tied to the ThermodynamicState, not the replica. @@ -1236,8 +1233,8 @@ def _propagate_replica(self, replica_id): logger.critical(message) raise SimulationNaNError(message) - # Return new positions and box vectors. - return sampler_state.positions, sampler_state.box_vectors + # Send the new state to the root node. We can ignore velocities as we're not saving them. + return sampler_state.__getstate__(ignore_velocities=True) def _get_replica_move_statistics(self, replica_id): """Return the statistics of the MCMCMove currently associated to this replica.""" diff --git a/openmmtools/multistate/replicaexchange.py b/openmmtools/multistate/replicaexchange.py index e017ef3d9..7c846f00a 100644 --- a/openmmtools/multistate/replicaexchange.py +++ b/openmmtools/multistate/replicaexchange.py @@ -269,8 +269,8 @@ def _mix_replicas(self): # otherwise fall back to Python-accelerated code. try: self._mix_all_replicas_cython() - except ValueError as e: - logger.warning(e.message) + except (ValueError, ImportError) as e: + logger.warning(str(e)) self._mix_all_replicas() else: assert self.replica_mixing_scheme is None diff --git a/openmmtools/multistate/sams.py b/openmmtools/multistate/sams.py index 8884bbcb8..a58a6466b 100644 --- a/openmmtools/multistate/sams.py +++ b/openmmtools/multistate/sams.py @@ -55,6 +55,8 @@ class SAMSSampler(multistate.MultiStateSampler): Thermodynamic state sampling scheme. One of ['global-jump', 'local-jump', 'restricted-range'] locality : int Number of neighboring states on either side to consider for local update schemes + weight_update : bool, default=True + If False, weights updating is disabled. This allows to perform expanded ensemble simulations. update_stages : str Number of stages to use for update. One of ['one-stage', 'two-stage'] weight_update_method : str @@ -102,11 +104,10 @@ class SAMSSampler(multistate.MultiStateSampler): >>> move = mcmc.GHMCMove(timestep=2.0*unit.femtoseconds, n_steps=50) >>> simulation = SAMSSampler(mcmc_moves=move, number_of_iterations=2, ... state_update_scheme='global-jump', locality=5, - ... update_stages='two-stage', flatness_criteria='logZ-flatness', - ... flatness_threshold=0.2, weight_update_method='rao-blackwellized', + ... update_stages='two-stage', histogram_flatness=0.5, + ... weight_update_method='rao-blackwellized', ... adapt_target_probabilities=False) - Create a single-replica SAMS simulation bound to a storage file and run: >>> storage_path = tempfile.NamedTemporaryFile(delete=False).name + '.nc' @@ -171,10 +172,14 @@ def __init__(self, log_target_probabilities=None, state_update_scheme='global-jump', locality=5, - update_stages='two-stage', - flatness_criteria='logZ-flatness', - flatness_threshold=0.2, + weight_update=True, weight_update_method='rao-blackwellized', + update_stages='two-stage', + histogram_flatness = 0.3, + minimum_visits = None, + minimum_round_trips = None, + minimum_logZ = None, + beta_factor=0.8, adapt_target_probabilities=False, gamma0=1.0, logZ_guess=None, @@ -195,23 +200,30 @@ def __init__(self, ``restricted-range`` will compute the probabilities for each of the states in the local neighborhood, increasing jump probability locality : int, optional, default=1 Number of neighboring states on either side to consider for local update schemes. - update_stages : str, optional, default='two-stage' - One of ['one-stage', 'two-stage'] - ``one-stage`` will use the asymptotically optimal scheme throughout the entire simulation (not recommended due to slow convergence) - ``two-stage`` will use a heuristic first stage to achieve flat histograms before switching to the asymptotically optimal scheme - flatness_criteria : string, optiona, default='logZ-flatness' - Method of assessing when to switch to asymptotically optimal scheme - One of ['logZ-flatness','minimum-visits','histogram-flatness'] - flatness_threshold : float, optional, default=0.2 - Histogram relative flatness threshold to use for first stage of two-stage scheme. + weight_update : bool, optional, default=True + If False, weights updating is disabled. This allows to perform expanded ensemble simulations. weight_update_method : str, optional, default='rao-blackwellized' Method to use for updating log weights in SAMS. One of ['optimal', 'rao-blackwellized'] ``rao-blackwellized`` will update log free energy estimate for all states for which energies were computed ``optimal`` will use integral counts to update log free energy estimate of current state only + update_stages : str, optional, default='two-stage' + One of ['one-stage', 'two-stage'] + ``one-stage`` will use the asymptotically optimal scheme throughout the entire simulation (not recommended due to slow convergence) + ``two-stage`` will use a heuristic first stage to achieve flat histograms before switching to the asymptotically optimal scheme + histogram_flatness: float, default=0.3 + Histogram relative flatness threshold to use in first stage of two-stage scheme. + minimum_round_trips : int, default=None + Minimum number of round trips to use in first stage of two-stage scheme. + minimum_visits : int, default=None + Minimum number of visits in each state to use in first stage of two-stage scheme. + minimum_logZ : float, default=None + Minimum logZ value to use in first stage of two-stage scheme. + beta_factor : float, optional, default=0.8 + Exponent for tunning the decaying rate of the gain factor. adapt_target_probabilities : bool, optional, default=False If True, target probabilities will be adapted to achieve minimal thermodynamic length between terminal thermodynamic states. (EXPERIMENTAL) - gamma0 : float, optional, default=0.0 + gamma0 : float, optional, default=1.0 Initial weight adaptation rate. logZ_guess : array-like of shape [n_states] of floats, optiona, default=None Initial guess for logZ for all states, if available. @@ -222,10 +234,14 @@ def __init__(self, self.log_target_probabilities = log_target_probabilities self.state_update_scheme = state_update_scheme self.locality = locality + self.weight_update = weight_update self.update_stages = update_stages - self.flatness_criteria = flatness_criteria - self.flatness_threshold = flatness_threshold self.weight_update_method = weight_update_method + self.histogram_flatness = histogram_flatness + self.minimum_round_trips = minimum_round_trips + self.minimum_visits = minimum_visits + self.minimum_logZ = minimum_logZ + self.beta_factor = beta_factor self.adapt_target_probabilities = adapt_target_probabilities self.gamma0 = gamma0 self.logZ_guess = logZ_guess @@ -234,6 +250,14 @@ def __init__(self, self._replica_neighbors = None self._cached_state_histogram = None + @property + def _criteria(self): + return { criteria: value for criteria, value in (('histogram_flatness', self.histogram_flatness), + ('minimum_round_trips', self.minimum_round_trips), + ('minimum_logZ', self.minimum_logZ), + ('minimum_visits', self.minimum_visits)) + if value is not None} + class _StoredProperty(multistate.MultiStateSampler._StoredProperty): @staticmethod @@ -253,14 +277,6 @@ def _update_stages_validator(instance, scheme): "are {}.".format(scheme, supported_schemes)) return scheme - @staticmethod - def _flatness_criteria_validator(instance, scheme): - supported_schemes = ['minimum-visits', 'logZ-flatness', 'histogram-flatness'] - if scheme not in supported_schemes: - raise ValueError("Unknown update scheme '{}'. Supported values " - "are {}.".format(scheme, supported_schemes)) - return scheme - @staticmethod def _weight_update_method_validator(instance, scheme): supported_schemes = ['optimal', 'rao-blackwellized'] @@ -280,15 +296,29 @@ def _adapt_target_probabilities_validator(instance, scheme): log_target_probabilities = _StoredProperty('log_target_probabilities', validate_function=None) state_update_scheme = _StoredProperty('state_update_scheme', validate_function=_StoredProperty._state_update_scheme_validator) locality = _StoredProperty('locality', validate_function=None) + weight_update = _StoredProperty('weight_update', validate_function=None) update_stages = _StoredProperty('update_stages', validate_function=_StoredProperty._update_stages_validator) - flatness_criteria = _StoredProperty('flatness_criteria', validate_function=_StoredProperty._flatness_criteria_validator) - flatness_threshold = _StoredProperty('flatness_threshold', validate_function=None) weight_update_method = _StoredProperty('weight_update_method', validate_function=_StoredProperty._weight_update_method_validator) + histogram_flatness = _StoredProperty('histogram_flatness', validate_function=None) + minimum_round_trips = _StoredProperty('minimum_round_trips', validate_function=None) + minimum_visits = _StoredProperty('minimum_visits', validate_function=None) + minimum_logZ = _StoredProperty('minimum_logZ', validate_function=None) + beta_factor = _StoredProperty('beta_factor', validate_function=None) adapt_target_probabilities = _StoredProperty('adapt_target_probabilities', validate_function=_StoredProperty._adapt_target_probabilities_validator) gamma0 = _StoredProperty('gamma0', validate_function=None) logZ_guess = _StoredProperty('logZ_guess', validate_function=None) def _initialize_stage(self): + if self.weight_update and (self.update_stages == 'two-stage'): + for key in self._criteria.keys(): + if key not in ['histogram_flatness', 'minimum_round_trips', 'minimum_visits', 'minimum_logZ']: + raise Exception('Unkown {} criteria. Supported values are: histogram_flatness, minimum_round_trips, minimum_logZ and minimum_visits'.format(key)) + + self._round_trips = 0 + # The variable _downhill keeps track of which end state the walker has visited more recently. + # This is used for computing the number of round trips. + # _downhill = False: the walker is going uphill because it has visited the intial state more recently than the final state + self._downhill = False self._t0 = 0 # reference iteration to subtract if self.update_stages == 'one-stage': self._stage = 1 # start with asymptotically-optimal stage @@ -367,23 +397,25 @@ def _restore_sampler_from_reporter(self, reporter): super()._restore_sampler_from_reporter(reporter) self._cached_state_histogram = self._compute_state_histogram(reporter=reporter) logger.debug('Restored state histogram: {}'.format(self._cached_state_histogram)) - data = reporter.read_online_analysis_data(self._iteration, 'logZ', 'stage', 't0') + data = reporter.read_online_analysis_data(self._iteration, 'logZ', 'round_trips', 'downhill', 't0', 'stage') self._logZ = data['logZ'] + self._round_trips = int(data['round_trips'][0]) + self._downhill = bool(int(data['downhill'][0])) self._stage = int(data['stage'][0]) self._t0 = int(data['t0'][0]) - # Compute log weights from log target probability and logZ estimate self._update_log_weights() - - # Determine t0 - self._update_stage() + if self.weight_update: + # Determine t0 + self._update_stage() @mpiplus.on_single_node(rank=0, broadcast_result=False, sync_nodes=False) @mpiplus.delayed_termination def _report_iteration_items(self): super(SAMSSampler, self)._report_iteration_items() - self._reporter.write_online_data_dynamic_and_static(self._iteration, logZ=self._logZ, stage=self._stage, t0=self._t0) + self._reporter.write_online_data_dynamic_and_static(self._iteration, logZ=self._logZ, + round_trips=self._round_trips, downhill=int(self._downhill), t0=self._t0, stage=self._stage) # Split into which states and how many samplers are in each state # Trying to do histogram[replica_thermo_states] += 1 does not correctly handle multiple # replicas in the same state. @@ -416,6 +448,14 @@ def _mix_replicas(self): else: raise Exception('Programming error: Unreachable code') + for replica_index, current_state_index in enumerate(self._replica_thermodynamic_states): + if self._downhill: + if current_state_index == 0: + self._round_trips += 1 + self._downhill = False + elif current_state_index == self.n_states-1: + self._downhill = True + # Determine fraction of swaps accepted this iteration. n_swaps_proposed = self._n_proposed_matrix.sum() n_swaps_accepted = self._n_accepted_matrix.sum() @@ -425,12 +465,15 @@ def _mix_replicas(self): swap_fraction_accepted = float(n_swaps_accepted) / n_swaps_proposed logger.debug("Accepted {}/{} attempted swaps ({:.1f}%)".format(n_swaps_accepted, n_swaps_proposed, swap_fraction_accepted * 100.0)) + if self.weight_update: + # Update logZ estimates + self._update_logZ_estimates(replicas_log_P_k) - # Update logZ estimates - self._update_logZ_estimates(replicas_log_P_k) + # Update log weights based on target probabilities + self._update_log_weights() - # Update log weights based on target probabilities - self._update_log_weights() + else: + logger.debug(' state histogram counts ({} total): {}'.format(self._cached_state_histogram.sum(), self._cached_state_histogram)) def _local_jump(self, replicas_log_P_k): n_replica, n_states, locality = self.n_replicas, self.n_states, self.locality @@ -562,41 +605,37 @@ def _update_stage(self): Determine which adaptation stage we're in by checking histogram flatness. """ - # TODO: Make minimum_visits a user option - minimum_visits = 1 + advance = {criteria: False for criteria, value in self._criteria.items() if value is not None} N_k = self._state_histogram logger.debug(' state histogram counts ({} total): {}'.format(self._cached_state_histogram.sum(), self._cached_state_histogram)) if (self.update_stages == 'two-stage') and (self._stage == 0): - advance = False if N_k.sum() == 0: # No samples yet; don't do anything. return - - if self.flatness_criteria == 'minimum-visits': - # Advance if every state has been visited at least once - if np.all(N_k >= minimum_visits): - advance = True - elif self.flatness_criteria == 'histogram-flatness': - # Check histogram flatness - empirical_pi_k = N_k[:] / N_k.sum() - pi_k = np.exp(self.log_target_probabilities) - relative_error_k = np.abs(pi_k - empirical_pi_k) / pi_k - if np.all(relative_error_k < self.flatness_threshold): - advance = True - elif self.flatness_criteria == 'logZ-flatness': - # TODO: Advance to asymptotically optimal scheme when logZ update fractional counts per state exceed threshold - # for all states. - criteria = abs(self._logZ / self.gamma0) > self.flatness_threshold - logger.debug('logZ-flatness criteria met (%d total): %s' % (np.sum(criteria), str(np.array(criteria, 'i1')))) - if np.all(criteria): - advance = True - else: - raise ValueError("Unknown flatness_criteria %s" % flatness_criteria) - - if advance or ((self._t0 > 0) and (self._iteration > self._t0)): - # Histograms are sufficiently flat; switch to asymptotically optimal scheme + for criteria,value in self._criteria.items(): + if criteria == 'histogram_flatness': + # Check histogram flatness + empirical_pi_k = N_k[:] / N_k.sum() + pi_k = np.exp(self.log_target_probabilities) + relative_error_k = np.abs(pi_k - empirical_pi_k) / pi_k + if np.all(relative_error_k < value): + advance['histogram_flatness'] = True + elif criteria == 'minimum_round_trips' and self._round_trips >= value: + # Check number of round_trips + advance['minimum_round_trips'] = True + elif criteria == 'minimum_visits' and np.all(N_k >= value): + # Check number of visits + advance['mimimum_visits'] = True + elif criteria == 'minimum_logZ': + # Check logZ values + criteria = np.abs(self._logZ / self.gamma0) > value + logger.debug('minimum_logZ criteria met (%d total): %s' % (np.sum(criteria), str(np.array(criteria, 'i1')))) + if np.all(criteria): + advance['minimum_logZ'] = True + + if (bool(advance) and all(v == True for v in advance.values())) or ((self._t0 > 0) and (self._iteration > self._t0)): + # switch to asymptotically optimal scheme self._stage = 1 # asymptotically optimal - # TODO: On resuming, we need to recompute or restore t0, or use some other way to compute it self._t0 = self._iteration - 1 def _update_logZ_estimates(self, replicas_log_P_k): @@ -628,13 +667,12 @@ def _update_logZ_estimates(self, replicas_log_P_k): for (replica_index, state_index) in enumerate(self._replica_thermodynamic_states): logger.debug(' Replica %d state %d' % (replica_index, state_index)) # Compute attenuation factor gamma - beta_factor = 0.8 pi_star = pi_k.min() t = float(self._iteration) if self._stage == 0: # initial stage - gamma = self.gamma0 * min(pi_star, t**(-beta_factor)) # Eq. 15 of [1] + gamma = self.gamma0 * min(pi_star, t**(-self.beta_factor)) # Eq. 15 of [1] elif self._stage == 1: - gamma = self.gamma0 * min(pi_star, (t - self._t0 + self._t0**beta_factor)**(-1)) # Eq. 15 of [1] + gamma = self.gamma0 * min(pi_star, (t - self._t0 + self._t0**self.beta_factor)**(-1)) # Eq. 15 of [1] else: raise Exception('stage {} unknown'.format(self._stage)) diff --git a/openmmtools/states.py b/openmmtools/states.py index aad42e21c..49b87990a 100644 --- a/openmmtools/states.py +++ b/openmmtools/states.py @@ -176,6 +176,8 @@ def reduced_potential_at_states(sampler_state, thermodynamic_states, context_cac for energy_idx, state_idx in enumerate(state_indices): reduced_potentials[state_idx] = compatible_energies[energy_idx] + return reduced_potentials + def group_by_compatibility(thermodynamic_states): """Utility function to split the thermodynamic states by compatibility. @@ -242,6 +244,23 @@ def _box_vectors_volume(box_vectors): return np.linalg.det(box_matrix) * a.unit**3 +def _box_vectors_area_xy(box_vectors): + """Return the xy-area of the box vectors. + + Parameters + ---------- + box_vectors : simtk.unit.Quantity + Vectors defining the box. + + Returns + ------- + + area_xy : simtk.unit.Quantity + The box area in units of length^2. + """ + return box_vectors[0][0] * box_vectors[1][1] + + # ============================================================================= # CUSTOM EXCEPTIONS # ============================================================================= @@ -281,11 +300,13 @@ class ThermodynamicsError(Exception): MULTIPLE_BAROSTATS, NO_BAROSTAT, UNSUPPORTED_BAROSTAT, + UNSUPPORTED_ANISOTROPIC_BAROSTAT, + SURFACE_TENSION_NOT_SUPPORTED, INCONSISTENT_BAROSTAT, BAROSTATED_NONPERIODIC, INCONSISTENT_INTEGRATOR, INCOMPATIBLE_SAMPLER_STATE, - INCOMPATIBLE_ENSEMBLE) = range(12) + INCOMPATIBLE_ENSEMBLE) = range(14) error_messages = { MULTIPLE_THERMOSTATS: "System has multiple thermostats.", @@ -294,6 +315,10 @@ class ThermodynamicsError(Exception): INCONSISTENT_THERMOSTAT: "System thermostat is inconsistent with thermodynamic state.", MULTIPLE_BAROSTATS: "System has multiple barostats.", UNSUPPORTED_BAROSTAT: "Found unsupported barostat {} in system.", + UNSUPPORTED_ANISOTROPIC_BAROSTAT: + "MonteCarloAnisotropicBarostat is only supported if the pressure along all scaled axes is the same.", + SURFACE_TENSION_NOT_SUPPORTED: + "Surface tension can only be set for states that have a system with a MonteCarloMembraneBarostat.", NO_BAROSTAT: "System does not have a barostat specifying the pressure.", INCONSISTENT_BAROSTAT: "System barostat is inconsistent with thermodynamic state.", BAROSTATED_NONPERIODIC: "Non-periodic systems cannot have a barostat.", @@ -362,11 +387,19 @@ class ThermodynamicState(object): state. It can be used to create new OpenMM Contexts, or to convert an existing Context to this particular thermodynamic state. - Only NVT and NPT ensembles are supported. The temperature must + NVT, NPT and NPgammaT ensembles are supported. The temperature must be specified in the constructor, either implicitly via a thermostat force in the system, or explicitly through the temperature parameter, which overrides an eventual thermostat indication. + To set a ThermodynamicState up in the NPgammaT ensemble, the system + passed to the constructor has to have a MonteCarloMembraneBarostat. + + To set a ThermodynamicState up with anisotropic pressure control, + the system passed to the constructor has to have a MonteCarloAnisotropicBarostat. + Currently the MonteCarloAnisotropicBarostat is only supported if + the pressure is equal for all axes that are under pressure control. + Parameters ---------- system : simtk.openmm.System @@ -382,12 +415,18 @@ class ThermodynamicState(object): or just set to this pressure in case it already exists. If None, the pressure is inferred from the system barostat, and NVT ensemble is assumed if there is no barostat. + surface_tension : simtk.unit.Quantity, optional + The surface tension for the system at constant surface tension. + If this is specified, the system must have a MonteCarloMembraneBarostat. + If None, the surface_tension is inferred from the barostat and + NPT/NVT ensemble is assumed if there is no MonteCarloMembraneBarostat. Attributes ---------- system temperature pressure + surface_tension volume n_particles @@ -461,8 +500,8 @@ class ThermodynamicState(object): # Public interface # ------------------------------------------------------------------------- - def __init__(self, system, temperature=None, pressure=None): - self._initialize(system, temperature, pressure) + def __init__(self, system, temperature=None, pressure=None, surface_tension=None): + self._initialize(system, temperature, pressure, surface_tension) @property def system(self): @@ -600,6 +639,7 @@ def get_system(self, remove_thermostat=False, remove_barostat=False): self._pop_barostat(system) else: # Set pressure of standard barostat. self._set_system_pressure(system, self.pressure) + self._set_system_surface_tension(system, self.surface_tension) # Set temperature of standard thermostat and barostat. if not (remove_barostat and remove_thermostat): @@ -677,6 +717,8 @@ def barostat(self): if barostat is not None: # NPT ensemble. self._set_barostat_pressure(barostat, self.pressure) self._set_barostat_temperature(barostat, self.temperature) + if self.surface_tension is not None: + self._set_barostat_surface_tension(barostat, self.surface_tension) return barostat @barostat.setter @@ -684,10 +726,15 @@ def barostat(self, new_barostat): # If None, just remove the barostat from the standard system. if new_barostat is None: self.pressure = None + self.surface_tension = None return - # Remember old pressure in case something goes wrong. + # Remember old pressure and surface tension in case something goes wrong. old_pressure = self.pressure + old_surface_tension = self.surface_tension + # make sure that the barostat type does not change + if self.barostat is not None and type(new_barostat) is not type(self.barostat): + raise ThermodynamicsError(ThermodynamicsError.INCONSISTENT_BAROSTAT) # Build the system with the new barostat. system = self.get_system(remove_barostat=True) @@ -696,10 +743,12 @@ def barostat(self, new_barostat): # Update the internally stored standard system, and restore the old # pressure if something goes wrong (e.g. the system is not periodic). try: - self._pressure = new_barostat.getDefaultPressure() + self._pressure = self._get_barostat_pressure(new_barostat) + self._surface_tension = self._get_barostat_surface_tension(new_barostat) self._unsafe_set_system(system, fix_state=False) except ThermodynamicsError: self._pressure = old_pressure + self._surface_tension = old_surface_tension raise @property @@ -750,6 +799,18 @@ def is_periodic(self): """True if the system is in a periodic box (read-only).""" return self._standard_system.usesPeriodicBoundaryConditions() + @property + def surface_tension(self): + """Surface tension""" + return self._surface_tension + + @surface_tension.setter + def surface_tension(self, gamma): + if (self._surface_tension is None) != (gamma is None): + raise ThermodynamicsError(ThermodynamicsError.SURFACE_TENSION_NOT_SUPPORTED) + else: + self._surface_tension = gamma + def reduced_potential(self, context_state): """Reduced potential in this thermodynamic state. @@ -766,15 +827,17 @@ def reduced_potential(self, context_state): Notes ----- - The reduced potential is defined as in Ref. [1] + The reduced potential is defined as in Ref. [1], + with a additional term for the surface tension - u = \beta [U(x) + p V(x) + \mu N(x)] + u = \beta [U(x) + p V(x) + \mu N(x) - \gamma A] where the thermodynamic parameters are \beta = 1/(kB T) is the inverse temperature p is the pressure \mu is the chemical potential + \gamma is the surface tension and the configurational properties are @@ -783,6 +846,7 @@ def reduced_potential(self, context_state): V(x) is the instantaneous box volume N(x) the numbers of various particle species (e.g. protons of titratible groups) + A(x) is the xy-area of the box. References ---------- @@ -827,17 +891,18 @@ def reduced_potential(self, context_state): openmm_state = context_state.getState(getEnergy=True) potential_energy = openmm_state.getPotentialEnergy() volume = openmm_state.getPeriodicBoxVolume() + area = _box_vectors_area_xy(openmm_state.getPeriodicBoxVectors()) else: n_particles = context_state.n_particles potential_energy = context_state.potential_energy volume = context_state.volume + area = context_state.area_xy # Check compatibility. if n_particles != self.n_particles: raise ThermodynamicsError(ThermodynamicsError.INCOMPATIBLE_SAMPLER_STATE) - return self._compute_reduced_potential(potential_energy, self.temperature, - volume, self.pressure) + volume, self.pressure, area, self.surface_tension) @classmethod def reduced_potential_at_states(cls, context, thermodynamic_states): @@ -878,7 +943,9 @@ def reduced_potential_at_states(cls, context, thermodynamic_states): # In NPT, we'll need also the volume. is_npt = thermodynamic_states[0].pressure is not None + is_npgammat = thermodynamic_states[0].surface_tension is not None volume = None + area_xy = None energy_by_force_group = {force.getForceGroup(): 0.0*unit.kilocalories_per_mole for force in context.getSystem().getForces()} @@ -904,11 +971,13 @@ def reduced_potential_at_states(cls, context, thermodynamic_states): # Compute volume if this is the first time we obtain a state. if is_npt and volume is None: volume = openmm_state.getPeriodicBoxVolume() + if is_npgammat and area_xy is None: + area_xy = _box_vectors_area_xy(openmm_state.getPeriodicBoxVectors()) # Compute the new total reduced potential. potential_energy = unit.sum(list(energy_by_force_group.values())) reduced_potential = cls._compute_reduced_potential(potential_energy, state.temperature, - volume, state.pressure) + volume, state.pressure, area_xy, state.surface_tension) reduced_potentials[state_idx] = reduced_potential # Update groups to compute for next states. @@ -1018,7 +1087,7 @@ def is_context_compatible(self, context): is_compatible = self._standard_system_hash == context_system_hash return is_compatible - def create_context(self, integrator, platform=None): + def create_context(self, integrator, platform=None, platform_properties=None): """Create a context in this ThermodynamicState. The context contains a copy of the system. If the integrator @@ -1042,6 +1111,9 @@ def create_context(self, integrator, platform=None): platform : simtk.openmm.Platform, optional Platform to use. If None, OpenMM tries to select the fastest available platform. Default is None. + platform_properties : dict, optional + A dictionary of platform properties. Requires platform to be + specified. Returns ------- @@ -1053,6 +1125,8 @@ def create_context(self, integrator, platform=None): ThermodynamicsError If the integrator has a temperature different from this ThermodynamicState. + ValueError + If platform_properties is specified, but platform is None Examples -------- @@ -1093,9 +1167,13 @@ def create_context(self, integrator, platform=None): # Create context. if platform is None: + if platform_properties is not None: + raise ValueError("To set platform_properties, you need to also specify the platform.") return openmm.Context(system, integrator) - else: + elif platform_properties is None: return openmm.Context(system, integrator, platform) + else: + return openmm.Context(system, integrator, platform, platform_properties) def apply_to_context(self, context): """Apply this ThermodynamicState to the context. @@ -1141,7 +1219,7 @@ def apply_to_context(self, context): 310.0 """ - self._set_context_barostat(context, update_pressure=True, update_temperature=True) + self._set_context_barostat(context, update_pressure=True, update_temperature=True, update_surface_tension=True) self._set_context_thermostat(context) # ------------------------------------------------------------------------- @@ -1193,12 +1271,13 @@ def __getstate__(self, skip_system=False): serialized_system = openmm.XmlSerializer.serialize(self._standard_system) serialized_system = zlib.compress(serialized_system.encode(self._ENCODING)) return dict(standard_system=serialized_system, temperature=self.temperature, - pressure=self.pressure) + pressure=self.pressure, surface_tension=self._surface_tension) def __setstate__(self, serialization): """Set the state from a dictionary representation.""" self._temperature = serialization['temperature'] self._pressure = serialization['pressure'] + self._surface_tension = serialization['surface_tension'] serialized_system = serialization['standard_system'] # Decompress system, if need be @@ -1227,7 +1306,7 @@ def __setstate__(self, serialization): # Internal-usage: initialization # ------------------------------------------------------------------------- - def _initialize(self, system, temperature=None, pressure=None): + def _initialize(self, system, temperature=None, pressure=None, surface_tension=None): """Initialize the thermodynamic state.""" # Avoid modifying the original system when setting temperature and pressure. system = copy.deepcopy(system) @@ -1235,10 +1314,19 @@ def _initialize(self, system, temperature=None, pressure=None): # If pressure is None, we try to infer the pressure from the barostat. barostat = self._find_barostat(system) if pressure is None and barostat is not None: - self._pressure = barostat.getDefaultPressure() + self._pressure = self._get_barostat_pressure(barostat) else: self._pressure = pressure # Pressure here can also be None. + # If surface tension is None, we try to infer the surface tension from the barostat. + barostat_type = type(barostat) + if surface_tension is None and barostat_type == openmm.MonteCarloMembraneBarostat: + self._surface_tension = barostat.getDefaultSurfaceTension() + elif surface_tension is not None and barostat_type != openmm.MonteCarloMembraneBarostat: + raise ThermodynamicsError(ThermodynamicsError.INCOMPATIBLE_ENSEMBLE) + else: + self._surface_tension = surface_tension + # If temperature is None, we infer the temperature from a thermostat. if temperature is None: thermostat = self._find_thermostat(system) @@ -1253,6 +1341,8 @@ def _initialize(self, system, temperature=None, pressure=None): self._set_system_temperature(system, temperature) if pressure is not None: self._set_system_pressure(system, pressure) + if surface_tension is not None: + self._set_system_surface_tension(system, surface_tension) # We can use the unsafe set_system since the system has been copied. self._unsafe_set_system(system, fix_state=False) @@ -1268,6 +1358,7 @@ def _initialize(self, system, temperature=None, pressure=None): # caused by unit conversion. _STANDARD_PRESSURE = 1.0*unit.bar _STANDARD_TEMPERATURE = 273.0*unit.kelvin + _STANDARD_SURFACE_TENSION = 0.0*unit.nanometer*unit.bar _NONPERIODIC_NONBONDED_METHODS = {openmm.NonbondedForce.NoCutoff, openmm.NonbondedForce.CutoffNonPeriodic} @@ -1283,12 +1374,13 @@ def _unsafe_set_system(self, system, fix_state): # Configure temperature and pressure. if fix_state: # We just need to add/remove the barostat according to the ensemble. - # Temperature and pressure of thermostat and barostat will be set + # Temperature, pressure, surface tension of thermostat and barostat will be set # to their standard value afterwards. self._set_system_pressure(system, self.pressure) + self._set_system_surface_tension(system, self.surface_tension) else: # If the flag is deactivated, we check that temperature - # and pressure of the system are correct. + # pressure, and surface tension of the system are correct. self._check_system_consistency(system) # Update standard system. @@ -1331,9 +1423,6 @@ def _check_system_consistency(self, system): # This line raises MULTIPLE_BAROSTATS and UNSUPPORTED_BAROSTAT. barostat = self._find_barostat(system) if barostat is not None: - if not self._is_barostat_consistent(barostat): - raise TE(TE.INCONSISTENT_BAROSTAT) - # Check that barostat is not added to non-periodic system. We # cannot use System.usesPeriodicBoundaryConditions() because # in OpenMM < 7.1 that returns True when a barostat is added. @@ -1343,6 +1432,10 @@ def _check_system_consistency(self, system): nonbonded_method = force.getNonbondedMethod() if nonbonded_method in self._NONPERIODIC_NONBONDED_METHODS: raise TE(TE.BAROSTATED_NONPERIODIC) + + if not self._is_barostat_consistent(barostat): + raise TE(TE.INCONSISTENT_BAROSTAT) + elif self.pressure is not None: raise TE(TE.NO_BAROSTAT) @@ -1386,7 +1479,9 @@ def _standardize_system(self, system): # Here we push the barostat at the end. barostat = self._pop_barostat(system) if barostat is not None: - barostat.setDefaultPressure(self._STANDARD_PRESSURE) + self._set_barostat_pressure(barostat, self._STANDARD_PRESSURE) + if isinstance(barostat, openmm.MonteCarloMembraneBarostat): + self._set_barostat_surface_tension(barostat, self._STANDARD_SURFACE_TENSION) system.addForce(barostat) def _compute_standard_system_hash(self, standard_system): @@ -1407,7 +1502,7 @@ def _update_standard_system(self, standard_system): # Internal-usage: context handling # ------------------------------------------------------------------------- - def _set_context_barostat(self, context, update_pressure, update_temperature): + def _set_context_barostat(self, context, update_pressure, update_temperature, update_surface_tension): """Set the barostat parameters in the Context.""" barostat = self._find_barostat(context.getSystem()) @@ -1415,14 +1510,22 @@ def _set_context_barostat(self, context, update_pressure, update_temperature): if (barostat is None) != (self._pressure is None): raise ThermodynamicsError(ThermodynamicsError.INCOMPATIBLE_ENSEMBLE) + if (type(barostat) is openmm.MonteCarloMembraneBarostat) == (self._surface_tension is None): + raise ThermodynamicsError(ThermodynamicsError.INCOMPATIBLE_ENSEMBLE) + # No need to set the barostat if we are in NVT. if self._pressure is None: return - # Apply pressure and temperature to barostat. + # Apply pressure, surface tension, and temperature to barostat. if update_pressure: self._set_barostat_pressure(barostat, self.pressure) - context.setParameter(barostat.Pressure(), self.pressure) + self._set_barostat_pressure_in_context(barostat, self.pressure, context) + + if self.surface_tension is not None and update_surface_tension: + self._set_barostat_surface_tension(barostat, self.surface_tension) + self._set_barostat_surface_tension_in_context(barostat, self.surface_tension, context) + if update_temperature: self._set_barostat_temperature(barostat, self.temperature) # TODO remove try except when drop openmm7.0 support @@ -1461,9 +1564,10 @@ def _apply_to_context_in_state(self, context, thermodynamic_state): """ update_pressure = self.pressure != thermodynamic_state.pressure update_temperature = self.temperature != thermodynamic_state.temperature + update_surface_tension = self.surface_tension != thermodynamic_state.surface_tension - if update_pressure or update_temperature: - self._set_context_barostat(context, update_pressure, update_temperature) + if update_pressure or update_temperature or update_surface_tension: + self._set_context_barostat(context, update_pressure, update_temperature, update_surface_tension) if update_temperature: self._set_context_thermostat(context) @@ -1544,7 +1648,7 @@ def set_temp(_integrator): # Internal-usage: barostat handling # ------------------------------------------------------------------------- - _SUPPORTED_BAROSTATS = {'MonteCarloBarostat'} + _SUPPORTED_BAROSTATS = {'MonteCarloBarostat', 'MonteCarloAnisotropicBarostat', 'MonteCarloMembraneBarostat'} @classmethod def _find_barostat(cls, system, get_index=False): @@ -1573,6 +1677,15 @@ def _find_barostat(cls, system, get_index=False): if barostat.__class__.__name__ not in cls._SUPPORTED_BAROSTATS: raise ThermodynamicsError(ThermodynamicsError.UNSUPPORTED_BAROSTAT, barostat.__class__.__name__) + elif isinstance(barostat, openmm.MonteCarloAnisotropicBarostat): + # support only if pressure in all scaled directions is equal + pressures = barostat.getDefaultPressure().value_in_unit(unit.bar) + scaled = [barostat.getScaleX(), barostat.getScaleY(), barostat.getScaleY()] + if sum(scaled) == 0: + raise ThermodynamicsError(ThermodynamicsError.UNSUPPORTED_ANISOTROPIC_BAROSTAT) + active_pressures = [pressure for pressure, active in zip(pressures, scaled) if active] + if any(abs(pressure - active_pressures[0]) > 0 for pressure in active_pressures): + raise ThermodynamicsError(ThermodynamicsError.UNSUPPORTED_ANISOTROPIC_BAROSTAT) if get_index: return force_idx, barostat return barostat @@ -1595,16 +1708,29 @@ def _pop_barostat(cls, system): return barostat return None + def _is_barostat_type_consistent(self, barostat): + # during initialization (standard system not set), any barostat type is OK + if not hasattr(self, "_standard_system"): + return True + system_barostat = self._find_barostat(self._standard_system) + return type(barostat) == type(system_barostat) + def _is_barostat_consistent(self, barostat): - """Check the barostat's temperature and pressure.""" + """Check the barostat's temperature, pressure, and surface_tension.""" try: barostat_temperature = barostat.getDefaultTemperature() except AttributeError: # versions previous to OpenMM 7.1 barostat_temperature = barostat.getTemperature() - barostat_pressure = barostat.getDefaultPressure() - is_consistent = utils.is_quantity_close(barostat_temperature, self.temperature) - is_consistent = is_consistent and utils.is_quantity_close(barostat_pressure, - self.pressure) + barostat_pressure = self._get_barostat_pressure(barostat) + barostat_surface_tension = self._get_barostat_surface_tension(barostat) + + is_consistent = self._is_barostat_type_consistent(barostat) + is_consistent = is_consistent and utils.is_quantity_close(barostat_temperature, self.temperature) + is_consistent = is_consistent and utils.is_quantity_close(barostat_pressure, self.pressure) + if barostat is not None and self._surface_tension is not None: + is_consistent = is_consistent and utils.is_quantity_close(barostat_surface_tension, self._surface_tension) + else: + is_consistent = is_consistent and (barostat_surface_tension == self._surface_tension) # both None return is_consistent def _set_system_pressure(self, system, pressure): @@ -1644,13 +1770,73 @@ def _set_system_pressure(self, system, pressure): @staticmethod def _set_barostat_pressure(barostat, pressure): """Set barostat pressure.""" - barostat.setDefaultPressure(pressure) + if isinstance(pressure, unit.Quantity): + pressure = pressure.value_in_unit(unit.bar) + if isinstance(barostat, openmm.MonteCarloAnisotropicBarostat): + barostat.setDefaultPressure(openmm.Vec3(pressure, pressure, pressure)*unit.bar) + else: + barostat.setDefaultPressure(pressure*unit.bar) + + @staticmethod + def _set_barostat_pressure_in_context(barostat, pressure, context): + """Set barostat pressure.""" + if isinstance(barostat, openmm.MonteCarloAnisotropicBarostat): + p = pressure.value_in_unit(unit.bar) + context.setParameter(barostat.Pressure(), openmm.Vec3(p, p, p)*unit.bar) + else: + context.setParameter(barostat.Pressure(), pressure) + + @staticmethod + def _get_barostat_pressure(barostat): + """Set barostat pressure.""" + if isinstance(barostat, openmm.MonteCarloAnisotropicBarostat): + scaled = [barostat.getScaleX(), barostat.getScaleY(), barostat.getScaleZ()] + first_scaled_axis = scaled.index(True) + return barostat.getDefaultPressure()[first_scaled_axis] + else: + return barostat.getDefaultPressure() @staticmethod def _set_barostat_temperature(barostat, temperature): """Set barostat temperature.""" barostat.setDefaultTemperature(temperature) + def _set_system_surface_tension(self, system, gamma): + """Set system surface tension""" + if gamma is not None and not system.usesPeriodicBoundaryConditions(): + raise ThermodynamicsError(ThermodynamicsError.BAROSTATED_NONPERIODIC) + barostat = self._find_barostat(system) + if (gamma is None) == isinstance(barostat, openmm.MonteCarloMembraneBarostat): + raise ThermodynamicsError(ThermodynamicsError.INCOMPATIBLE_ENSEMBLE) + self._set_barostat_surface_tension(barostat, gamma) + + def _set_barostat_surface_tension(self, barostat, gamma): + # working around a bug in the unit conversion https://github.com/openmm/openmm/issues/2406 + if isinstance(gamma, unit.Quantity): + gamma = gamma.value_in_unit(unit.bar * unit.nanometer) + if isinstance(barostat, openmm.MonteCarloMembraneBarostat): + barostat.setDefaultSurfaceTension(gamma) + elif gamma is not None: + raise ThermodynamicsError(ThermodynamicsError.SURFACE_TENSION_NOT_SUPPORTED) + + def _get_barostat_surface_tension(self, barostat): + if isinstance(barostat, openmm.MonteCarloMembraneBarostat): + return barostat.getDefaultSurfaceTension() + else: + return None + + @staticmethod + def _set_barostat_surface_tension_in_context(barostat, surface_tension, context): + """Set barostat surface tension.""" + # work around a unit conversion issue in openmm + if isinstance(surface_tension, unit.Quantity): + surface_tension = surface_tension.value_in_unit(unit.nanometer*unit.bar) + try: + context.getParameter(barostat.SurfaceTension()) + except Exception: + raise ThermodynamicsError(ThermodynamicsError.INCOMPATIBLE_ENSEMBLE) + context.setParameter(barostat.SurfaceTension(), surface_tension) + # ------------------------------------------------------------------------- # Internal-usage: thermostat handling # ------------------------------------------------------------------------- @@ -1715,12 +1901,14 @@ def _set_system_temperature(cls, system, temperature): # ------------------------------------------------------------------------- @staticmethod - def _compute_reduced_potential(potential_energy, temperature, volume, pressure): + def _compute_reduced_potential(potential_energy, temperature, volume, pressure, area_xy=None, surface_tension=None): """Convert potential energy into reduced potential.""" beta = 1.0 / (unit.BOLTZMANN_CONSTANT_kB * temperature) reduced_potential = potential_energy / unit.AVOGADRO_CONSTANT_NA if pressure is not None: reduced_potential += pressure * volume + if area_xy is not None and surface_tension is not None: + reduced_potential -= surface_tension * area_xy return beta * reduced_potential def _find_force_groups_to_update(self, context, thermodynamic_state, memo): @@ -1985,6 +2173,11 @@ def volume(self): """The volume of the box (read-only)""" return _box_vectors_volume(self.box_vectors) + @property + def area_xy(self): + """The xy-area of the box (read-only)""" + return _box_vectors_area_xy(self.box_vectors) + @property def n_particles(self): """Number of particles (read-only).""" diff --git a/openmmtools/tests/test_alchemy.py b/openmmtools/tests/test_alchemy.py index 37383ebfd..03e11a57b 100644 --- a/openmmtools/tests/test_alchemy.py +++ b/openmmtools/tests/test_alchemy.py @@ -211,8 +211,7 @@ def turn_off_nonbonded(system, sterics=False, electrostatics=False, epsilon_coeff*epsilon_scale) - -def dissect_nonbonded_energy(reference_system, positions, alchemical_atoms): +def dissect_nonbonded_energy(reference_system, positions, alchemical_atoms, other_alchemical_atoms): """Dissect the nonbonded energy contributions of the reference system by atom group and sterics/electrostatics. @@ -227,6 +226,8 @@ def dissect_nonbonded_energy(reference_system, positions, alchemical_atoms): The positions to test. alchemical_atoms : set of int The indices of the alchemical atoms. + other_alchemical_atoms : set of int + The indices of the alchemical atoms in other alchemical regions Returns ------- @@ -249,7 +250,8 @@ def dissect_nonbonded_energy(reference_system, positions, alchemical_atoms): na_reciprocal_energy: electrostatics of reciprocal space between nonalchemical-alchemical atoms """ - nonalchemical_atoms = set(range(reference_system.getNumParticles())).difference(alchemical_atoms) + all_alchemical_atoms = set(alchemical_atoms).union(other_alchemical_atoms) + nonalchemical_atoms = set(range(reference_system.getNumParticles())).difference(all_alchemical_atoms) # Remove all forces but NonbondedForce and eventually the # CustomNonbondedForce used to model reaction field. @@ -270,6 +272,11 @@ def dissect_nonbonded_energy(reference_system, positions, alchemical_atoms): # Compute particle interactions between different groups of atoms # ---------------------------------------------------------------- + # Turn off other alchemical regions + if len(other_alchemical_atoms) > 0: + turn_off_nonbonded(reference_system, sterics=True, electrostatics=True, only_atoms=other_alchemical_atoms) + turn_off_nonbonded(reference_system, sterics=True, electrostatics=True, exceptions=True, only_atoms=other_alchemical_atoms) + system = copy.deepcopy(reference_system) # Compute total energy from nonbonded interactions @@ -438,7 +445,8 @@ def is_alchemical_pme_treatment_exact(alchemical_system): only_one=True) for parameter_idx in range(nonbonded_force.getNumGlobalParameters()): parameter_name = nonbonded_force.getGlobalParameterName(parameter_idx) - if parameter_name == 'lambda_electrostatics': + # With multiple alchemical regions, lambda_electrostatics might have a suffix. + if parameter_name.startswith('lambda_electrostatics'): return True return False @@ -454,7 +462,11 @@ def compare_system_energies(reference_system, alchemical_system, alchemical_regi method is an Ewald method. """ - force_group = -1 # Default we compare the energy of all groups. + if not isinstance(alchemical_regions, list): + alchemical_regions = [alchemical_regions] + + # Default we compare the energy of all groups. + force_group = -1 # Check nonbonded method. Comparing with PME is more complicated # because the alchemical system with direct-space treatment of PME @@ -479,8 +491,13 @@ def compare_system_energies(reference_system, alchemical_system, alchemical_regi # Compute the reciprocal space correction added to the direct space # energy due to the exceptions of the alchemical atoms. - alchemical_atoms = alchemical_regions.alchemical_atoms - aa_correction, na_correction = compute_direct_space_correction(nonbonded_force, alchemical_atoms, positions) + aa_correction = 0.0 * unit.kilojoule_per_mole + na_correction = 0.0 * unit.kilojoule_per_mole + for region in alchemical_regions: + alchemical_atoms = region.alchemical_atoms + aa, na = compute_direct_space_correction(nonbonded_force, alchemical_atoms, positions) + aa_correction += aa + na_correction += na # Compute potential of the direct space. potentials = [compute_energy(system, positions, force_group=force_group) @@ -503,7 +520,38 @@ def compare_system_energies(reference_system, alchemical_system, alchemical_regi raise Exception(err_msg.format(delta / unit.kilocalories_per_mole, MAX_DELTA / unit.kilocalories_per_mole)) -def check_interacting_energy_components(reference_system, alchemical_system, alchemical_regions, positions): +def check_multi_interacting_energy_components(reference_system, alchemical_system, alchemical_regions, positions): + """wrapper around check_interacting_energy_components for multiple regions + + Parameters + ---------- + reference_system : simtk.openmm.System + The reference system. + alchemical_system : simtk.openmm.System + The alchemically modified system to test. + alchemical_regions : AlchemicalRegion. + The alchemically modified region. + positions : n_particlesx3 array-like of simtk.openmm.unit.Quantity + The positions to test (units of length). + + Note + ---------- + Interactions between alchemical regions are not tested here. + Alchemical regions are assumed to be non interacting. + """ + + all_alchemical_atoms = set() + for region in alchemical_regions: + for atom in region.alchemical_atoms: + all_alchemical_atoms.add(atom) + for region in alchemical_regions: + check_interacting_energy_components( + reference_system, alchemical_system, region, positions, + all_alchemical_atoms, multi_regions=True) + + +def check_interacting_energy_components(reference_system, alchemical_system, alchemical_regions, positions, + all_alchemical_atoms=None, multi_regions=False): """Compare full and alchemically-modified system energies by energy component. Parameters @@ -516,6 +564,8 @@ def check_interacting_energy_components(reference_system, alchemical_system, alc The alchemically modified region. positions : n_particlesx3 array-like of simtk.openmm.unit.Quantity The positions to test (units of length). + multi_regions : boolean + Indicates if mutiple regions are being tested """ energy_unit = unit.kilojoule_per_mole @@ -528,9 +578,15 @@ def check_interacting_energy_components(reference_system, alchemical_system, alc nonbonded_method = nonbonded_force.getNonbondedMethod() # Get energy components of reference system's nonbonded force - print("Dissecting reference system's nonbonded force") + if multi_regions: + other_alchemical_atoms = all_alchemical_atoms.difference(alchemical_regions.alchemical_atoms) + print("Dissecting reference system's nonbonded force for region {}".format(alchemical_regions.name)) + else: + other_alchemical_atoms = set() + print("Dissecting reference system's nonbonded force") + energy_components = dissect_nonbonded_energy(reference_system, positions, - alchemical_regions.alchemical_atoms) + alchemical_regions.alchemical_atoms, other_alchemical_atoms) nn_particle_sterics, aa_particle_sterics, na_particle_sterics,\ nn_particle_electro, aa_particle_electro, na_particle_electro,\ nn_exception_sterics, aa_exception_sterics, na_exception_sterics,\ @@ -538,9 +594,12 @@ def check_interacting_energy_components(reference_system, alchemical_system, alc nn_reciprocal_energy, aa_reciprocal_energy, na_reciprocal_energy = energy_components # Dissect unmodified nonbonded force in alchemical system - print("Dissecting alchemical system's unmodified nonbonded force") + if multi_regions: + print("Dissecting alchemical system's unmodified nonbonded force for region {}".format(alchemical_regions.name)) + else: + print("Dissecting alchemical system's unmodified nonbonded force") energy_components = dissect_nonbonded_energy(alchemical_system, positions, - alchemical_regions.alchemical_atoms) + alchemical_regions.alchemical_atoms, other_alchemical_atoms) unmod_nn_particle_sterics, unmod_aa_particle_sterics, unmod_na_particle_sterics,\ unmod_nn_particle_electro, unmod_aa_particle_electro, unmod_na_particle_electro,\ unmod_nn_exception_sterics, unmod_aa_exception_sterics, unmod_na_exception_sterics,\ @@ -548,24 +607,31 @@ def check_interacting_energy_components(reference_system, alchemical_system, alc unmod_nn_reciprocal_energy, unmod_aa_reciprocal_energy, unmod_na_reciprocal_energy = energy_components # Get alchemically-modified energy components - print("Computing alchemical system components energies") - alchemical_state = AlchemicalState.from_system(alchemical_system) + if multi_regions: + print("Computing alchemical system components energies for region {}".format(alchemical_regions.name)) + else: + print("Computing alchemical system components energies") + alchemical_state = AlchemicalState.from_system(alchemical_system, parameters_name_suffix=alchemical_regions.name) alchemical_state.set_alchemical_parameters(1.0) energy_components = AbsoluteAlchemicalFactory.get_energy_components(alchemical_system, alchemical_state, positions, platform=GLOBAL_ALCHEMY_PLATFORM) + if multi_regions: + region_label = ' for region {}'.format(alchemical_regions.name) + else: + region_label = '' # Sterics particle and exception interactions are always modeled with a custom force. - na_custom_particle_sterics = energy_components['alchemically modified NonbondedForce for non-alchemical/alchemical sterics'] - aa_custom_particle_sterics = energy_components['alchemically modified NonbondedForce for alchemical/alchemical sterics'] - na_custom_exception_sterics = energy_components['alchemically modified BondForce for non-alchemical/alchemical sterics exceptions'] - aa_custom_exception_sterics = energy_components['alchemically modified BondForce for alchemical/alchemical sterics exceptions'] + na_custom_particle_sterics = energy_components['alchemically modified NonbondedForce for non-alchemical/alchemical sterics' + region_label] + aa_custom_particle_sterics = energy_components['alchemically modified NonbondedForce for alchemical/alchemical sterics' + region_label] + na_custom_exception_sterics = energy_components['alchemically modified BondForce for non-alchemical/alchemical sterics exceptions' + region_label] + aa_custom_exception_sterics = energy_components['alchemically modified BondForce for alchemical/alchemical sterics exceptions' + region_label] # With exact treatment of PME, we use the NonbondedForce offset for electrostatics. try: - na_custom_particle_electro = energy_components['alchemically modified NonbondedForce for non-alchemical/alchemical electrostatics'] - aa_custom_particle_electro = energy_components['alchemically modified NonbondedForce for alchemical/alchemical electrostatics'] - na_custom_exception_electro = energy_components['alchemically modified BondForce for non-alchemical/alchemical electrostatics exceptions'] - aa_custom_exception_electro = energy_components['alchemically modified BondForce for alchemical/alchemical electrostatics exceptions'] + na_custom_particle_electro = energy_components['alchemically modified NonbondedForce for non-alchemical/alchemical electrostatics' + region_label] + aa_custom_particle_electro = energy_components['alchemically modified NonbondedForce for alchemical/alchemical electrostatics' + region_label] + na_custom_exception_electro = energy_components['alchemically modified BondForce for non-alchemical/alchemical electrostatics exceptions' + region_label] + aa_custom_exception_electro = energy_components['alchemically modified BondForce for alchemical/alchemical electrostatics exceptions' + region_label] except KeyError: assert is_exact_pme @@ -589,41 +655,41 @@ def check_interacting_energy_components(reference_system, alchemical_system, alc # Check sterics interactions match assert_almost_equal(nn_particle_sterics, unmod_nn_particle_sterics, - 'Non-alchemical/non-alchemical atoms particle sterics') + 'Non-alchemical/non-alchemical atoms particle sterics' + region_label) assert_almost_equal(nn_exception_sterics, unmod_nn_exception_sterics, - 'Non-alchemical/non-alchemical atoms exceptions sterics') + 'Non-alchemical/non-alchemical atoms exceptions sterics' + region_label) assert_almost_equal(aa_particle_sterics, aa_custom_particle_sterics, - 'Alchemical/alchemical atoms particle sterics') + 'Alchemical/alchemical atoms particle sterics' + region_label) assert_almost_equal(aa_exception_sterics, aa_custom_exception_sterics, - 'Alchemical/alchemical atoms exceptions sterics') + 'Alchemical/alchemical atoms exceptions sterics' + region_label) assert_almost_equal(na_particle_sterics, na_custom_particle_sterics, - 'Non-alchemical/alchemical atoms particle sterics') + 'Non-alchemical/alchemical atoms particle sterics' + region_label) assert_almost_equal(na_exception_sterics, na_custom_exception_sterics, - 'Non-alchemical/alchemical atoms exceptions sterics') + 'Non-alchemical/alchemical atoms exceptions sterics' + region_label) # Check electrostatics interactions assert_almost_equal(nn_particle_electro, unmod_nn_particle_electro, - 'Non-alchemical/non-alchemical atoms particle electrostatics') + 'Non-alchemical/non-alchemical atoms particle electrostatics' + region_label) assert_almost_equal(nn_exception_electro, unmod_nn_exception_electro, - 'Non-alchemical/non-alchemical atoms exceptions electrostatics') + 'Non-alchemical/non-alchemical atoms exceptions electrostatics' + region_label) # With exact treatment of PME, the electrostatics of alchemical-alchemical # atoms is modeled with NonbondedForce offsets. if is_exact_pme: # Reciprocal space. assert_almost_equal(aa_reciprocal_energy, unmod_aa_reciprocal_energy, - 'Alchemical/alchemical atoms reciprocal space energy') + 'Alchemical/alchemical atoms reciprocal space energy' + region_label) assert_almost_equal(na_reciprocal_energy, unmod_na_reciprocal_energy, - 'Non-alchemical/alchemical atoms reciprocal space energy') + 'Non-alchemical/alchemical atoms reciprocal space energy' + region_label) # Direct space. assert_almost_equal(aa_particle_electro, unmod_aa_particle_electro, - 'Alchemical/alchemical atoms particle electrostatics') + 'Alchemical/alchemical atoms particle electrostatics' + region_label) assert_almost_equal(na_particle_electro, unmod_na_particle_electro, - 'Non-alchemical/alchemical atoms particle electrostatics') + 'Non-alchemical/alchemical atoms particle electrostatics' + region_label) # Exceptions. assert_almost_equal(aa_exception_electro, unmod_aa_exception_electro, - 'Alchemical/alchemical atoms exceptions electrostatics') + 'Alchemical/alchemical atoms exceptions electrostatics' + region_label) assert_almost_equal(na_exception_electro, unmod_na_exception_electro, - 'Non-alchemical/alchemical atoms exceptions electrostatics') + 'Non-alchemical/alchemical atoms exceptions electrostatics' + region_label) # With direct space PME, the custom forces model only the # direct space of alchemical-alchemical interactions. else: @@ -636,14 +702,14 @@ def check_interacting_energy_components(reference_system, alchemical_system, alc # Check direct space energy assert_almost_equal(aa_particle_electro, aa_custom_particle_electro, - 'Alchemical/alchemical atoms particle electrostatics') + 'Alchemical/alchemical atoms particle electrostatics' + region_label) assert_almost_equal(na_particle_electro, na_custom_particle_electro, - 'Non-alchemical/alchemical atoms particle electrostatics') + 'Non-alchemical/alchemical atoms particle electrostatics' + region_label) # Check exceptions. assert_almost_equal(aa_exception_electro, aa_custom_exception_electro, - 'Alchemical/alchemical atoms exceptions electrostatics') + 'Alchemical/alchemical atoms exceptions electrostatics' + region_label) assert_almost_equal(na_exception_electro, na_custom_exception_electro, - 'Non-alchemical/alchemical atoms exceptions electrostatics') + 'Non-alchemical/alchemical atoms exceptions electrostatics' + region_label) # With Ewald methods, the NonbondedForce should always hold the # reciprocal space energy of nonalchemical-nonalchemical atoms. @@ -677,9 +743,8 @@ def check_interacting_energy_components(reference_system, alchemical_system, alc '{} energy '.format(force_name)) -def check_noninteracting_energy_components(reference_system, alchemical_system, alchemical_regions, positions): - """Check non-interacting energy components are zero when appropriate. - +def check_multi_noninteracting_energy_components(reference_system, alchemical_system, alchemical_regions, positions): + """wrapper around check_noninteracting_energy_components for multiple regions Parameters ---------- reference_system : simtk.openmm.System @@ -690,18 +755,40 @@ def check_noninteracting_energy_components(reference_system, alchemical_system, The alchemically modified region. positions : n_particlesx3 array-like of simtk.openmm.unit.Quantity The positions to test (units of length). + """ + for region in alchemical_regions: + check_noninteracting_energy_components(reference_system, alchemical_system, region, positions, True) + +def check_noninteracting_energy_components(reference_system, alchemical_system, alchemical_regions, positions, multi_regions=False): + """Check non-interacting energy components are zero when appropriate. + Parameters + ---------- + reference_system : simtk.openmm.System + The reference system (not alchemically modified). + alchemical_system : simtk.openmm.System + The alchemically modified system to test. + alchemical_regions : AlchemicalRegion. + The alchemically modified region. + positions : n_particlesx3 array-like of simtk.openmm.unit.Quantity + The positions to test (units of length). + multi_regions : boolean + Indicates if mutiple regions are being tested """ alchemical_system = copy.deepcopy(alchemical_system) is_exact_pme = is_alchemical_pme_treatment_exact(alchemical_system) # Set state to non-interacting. - alchemical_state = AlchemicalState.from_system(alchemical_system) + alchemical_state = AlchemicalState.from_system(alchemical_system, parameters_name_suffix=alchemical_regions.name) alchemical_state.set_alchemical_parameters(0.0) energy_components = AbsoluteAlchemicalFactory.get_energy_components(alchemical_system, alchemical_state, positions, platform=GLOBAL_ALCHEMY_PLATFORM) def assert_zero_energy(label): + # Handle multiple alchemical regions. + if multi_regions: + label = label + ' for region ' + alchemical_regions.name + # Testing energy component of each region. print('testing {}'.format(label)) value = energy_components[label] assert abs(value / GLOBAL_ENERGY_UNIT) == 0.0, ("'{}' should have zero energy in annihilated alchemical" @@ -811,44 +898,47 @@ def assert_zero_energy(label): 'reference {}, alchemical {}'.format(reference_force_energy, alchemical_energy)) -def check_split_force_groups(system): +def check_split_force_groups(system, region_names=None): """Check that force groups are split correctly.""" - force_groups_by_lambda = {} - lambdas_by_force_group = {} + if region_names is None: + region_names = [] # Separate forces groups by lambda parameters that AlchemicalState supports. - for force, lambda_name, _ in AlchemicalState._get_system_controlled_parameters( - system, parameters_name_suffix=None): - force_group = force.getForceGroup() - try: - force_groups_by_lambda[lambda_name].add(force_group) - except KeyError: - force_groups_by_lambda[lambda_name] = {force_group} - try: - lambdas_by_force_group[force_group].add(lambda_name) - except KeyError: - lambdas_by_force_group[force_group] = {lambda_name} - - # Check that force group 0 doesn't hold alchemical forces. - assert 0 not in force_groups_by_lambda - - # There are as many alchemical force groups as not-None lambda variables. - alchemical_state = AlchemicalState.from_system(system) - valid_lambdas = {lambda_name for lambda_name in alchemical_state._get_controlled_parameters() - if getattr(alchemical_state, lambda_name) is not None} - assert valid_lambdas == set(force_groups_by_lambda.keys()) - - # Check that force groups and lambda variables are in 1-to-1 correspondence. - assert len(force_groups_by_lambda) == len(lambdas_by_force_group) - for d in [force_groups_by_lambda, lambdas_by_force_group]: - for value in d.values(): - assert len(value) == 1 - - # With exact treatment of PME, the NonbondedForce must - # be in the lambda_electrostatics force group. - if is_alchemical_pme_treatment_exact(system): - force_idx, nonbonded_force = forces.find_forces(system, openmm.NonbondedForce, only_one=True) - assert force_groups_by_lambda['lambda_electrostatics'] == {nonbonded_force.getForceGroup()} + for region in region_names: + force_groups_by_lambda = {} + lambdas_by_force_group = {} + for force, lambda_name, _ in AlchemicalState._get_system_controlled_parameters( + system, parameters_name_suffix=region): + force_group = force.getForceGroup() + try: + force_groups_by_lambda[lambda_name].add(force_group) + except KeyError: + force_groups_by_lambda[lambda_name] = {force_group} + try: + lambdas_by_force_group[force_group].add(lambda_name) + except KeyError: + lambdas_by_force_group[force_group] = {lambda_name} + + # Check that force group 0 doesn't hold alchemical forces. + assert 0 not in force_groups_by_lambda + + # There are as many alchemical force groups as not-None lambda variables. + alchemical_state = AlchemicalState.from_system(system, parameters_name_suffix=region) + valid_lambdas = {lambda_name for lambda_name in alchemical_state._get_controlled_parameters(parameters_name_suffix=region) + if getattr(alchemical_state, lambda_name) is not None} + assert valid_lambdas == set(force_groups_by_lambda.keys()) + + # Check that force groups and lambda variables are in 1-to-1 correspondence. + assert len(force_groups_by_lambda) == len(lambdas_by_force_group) + for d in [force_groups_by_lambda, lambdas_by_force_group]: + for value in d.values(): + assert len(value) == 1 + + # With exact treatment of PME, the NonbondedForce must + # be in the lambda_electrostatics force group. + if is_alchemical_pme_treatment_exact(system): + force_idx, nonbonded_force = forces.find_forces(system, openmm.NonbondedForce, only_one=True) + assert force_groups_by_lambda['lambda_electrostatics_{}'.format(region)] == {nonbonded_force.getForceGroup()} # ============================================================================= @@ -1221,7 +1311,6 @@ def test_resolve_alchemical_region(): with nose.tools.assert_raises(ValueError): AbsoluteAlchemicalFactory._resolve_alchemical_region(system, alchemical_region) - class TestAbsoluteAlchemicalFactory(object): """Test AbsoluteAlchemicalFactory class.""" @@ -1268,11 +1357,16 @@ def define_regions(cls): cls.test_regions = dict() cls.test_regions['LennardJonesCluster'] = AlchemicalRegion(alchemical_atoms=range(2)) cls.test_regions['LennardJonesFluid'] = AlchemicalRegion(alchemical_atoms=range(10)) - cls.test_regions['TIP3P WaterBox'] = AlchemicalRegion(alchemical_atoms=range(3)) - cls.test_regions['TIP4P-EW WaterBox and NaCl'] = AlchemicalRegion(alchemical_atoms=range(4)) # Modify ions. cls.test_regions['Toluene'] = AlchemicalRegion(alchemical_atoms=range(6)) # Only partially modified. cls.test_regions['AlanineDipeptide'] = AlchemicalRegion(alchemical_atoms=range(22)) cls.test_regions['HostGuestExplicit'] = AlchemicalRegion(alchemical_atoms=range(126, 156)) + cls.test_regions['TIP3P WaterBox'] = AlchemicalRegion(alchemical_atoms=range(0,3)) + + # Modify ions. + for atom in cls.test_systems['TIP4P-EW WaterBox and NaCl with PME'].topology.atoms(): + if atom.name in ['Na', 'Cl']: + cls.test_regions['TIP4P-EW WaterBox and NaCl'] = AlchemicalRegion(alchemical_atoms=range(atom.index, atom.index+1)) + break @classmethod def generate_cases(cls): @@ -1440,6 +1534,208 @@ def test_overlap(self): f.description = "Testing reference/alchemical overlap for {}".format(test_name) yield f +class TestMultiRegionAbsoluteAlchemicalFactory(TestAbsoluteAlchemicalFactory): + """Test AbsoluteAlchemicalFactory class using multiple regions.""" + + @classmethod + def define_systems(cls): + """Create shared test systems in cls.test_systems for the test suite.""" + cls.test_systems = dict() + + # Basic test systems: Lennard-Jones and water particles only. + # Test also dispersion correction and switch off ("on" values + # for these options are tested in HostGuestExplicit system). + cls.test_systems['LennardJonesCluster'] = testsystems.LennardJonesCluster() + cls.test_systems['LennardJonesFluid with dispersion correction'] = \ + testsystems.LennardJonesFluid(nparticles=100, dispersion_correction=True) + cls.test_systems['TIP3P WaterBox with reaction field, no switch, no dispersion correction'] = \ + testsystems.WaterBox(dispersion_correction=False, switch=False, nonbondedMethod=openmm.app.CutoffPeriodic) + cls.test_systems['HostGuestExplicit with PME'] = \ + testsystems.HostGuestExplicit(nonbondedMethod=openmm.app.PME) + cls.test_systems['HostGuestExplicit with CutoffPeriodic'] = \ + testsystems.HostGuestExplicit(nonbondedMethod=openmm.app.CutoffPeriodic) + + @classmethod + def define_regions(cls): + """Create shared AlchemicalRegions for test systems in cls.test_regions.""" + cls.test_region_zero = dict() + cls.test_region_one = dict() + cls.test_region_two = dict() + + cls.test_region_zero['LennardJonesCluster'] = AlchemicalRegion(alchemical_atoms=range(2), name='zero') + cls.test_region_one['LennardJonesCluster'] = AlchemicalRegion(alchemical_atoms=range(2,4), name='one') + cls.test_region_two['LennardJonesCluster'] = AlchemicalRegion(alchemical_atoms=range(4,6), name='two') + cls.test_region_zero['LennardJonesFluid'] = AlchemicalRegion(alchemical_atoms=range(10), name='zero') + cls.test_region_one['LennardJonesFluid'] = AlchemicalRegion(alchemical_atoms=range(10,20), name='one') + cls.test_region_two['LennardJonesFluid'] = AlchemicalRegion(alchemical_atoms=range(20,30), name='two') + cls.test_region_zero['TIP3P WaterBox'] = AlchemicalRegion(alchemical_atoms=range(3), name='zero') + cls.test_region_one['TIP3P WaterBox'] = AlchemicalRegion(alchemical_atoms=range(3,6), name='one') + cls.test_region_two['TIP3P WaterBox'] = AlchemicalRegion(alchemical_atoms=range(6,9), name='two') + #Three regions push HostGuest system beyond 32 force groups + cls.test_region_zero['HostGuestExplicit'] = AlchemicalRegion(alchemical_atoms=range(126, 156), name='zero') + cls.test_region_one['HostGuestExplicit'] = AlchemicalRegion(alchemical_atoms=range(156,160), name='one') + cls.test_region_two['HostGuestExplicit'] = None + + @classmethod + def generate_cases(cls): + """Generate all test cases in cls.test_cases combinatorially.""" + cls.test_cases = dict() + direct_space_factory = AbsoluteAlchemicalFactory(alchemical_pme_treatment='direct-space', + alchemical_rf_treatment='switched') + exact_pme_factory = AbsoluteAlchemicalFactory(alchemical_pme_treatment='exact') + + # We generate all possible combinations of annihilate_sterics/electrostatics + # for each test system. We also annihilate bonds, angles and torsions every + # 3 test cases so that we test it at least one for each test system and for + # each combination of annihilate_sterics/electrostatics. + n_test_cases = 0 + for test_system_name, test_system in cls.test_systems.items(): + + # Find standard alchemical region zero. + for region_name_zero, region_zero in cls.test_region_zero.items(): + if region_name_zero in test_system_name: + break + assert region_name_zero in test_system_name, test_system_name + + # Find standard alchemical region one. + for region_name_one, region_one in cls.test_region_one.items(): + if region_name_one in test_system_name: + break + assert region_name_one in test_system_name, test_system_name + + # Find standard alchemical region two. + for region_name_two, region_two in cls.test_region_two.items(): + if region_name_two in test_system_name: + break + assert region_name_two in test_system_name, test_system_name + + assert region_name_zero == region_name_one and region_name_one == region_name_two + #We only want two regions for HostGuest or we get too many force groups + if 'HostGuestExplicit' in region_name_one: + test_regions = [region_zero, region_one] + else: + test_regions = [region_zero, region_one, region_two] + + # Find nonbonded method. + force_idx, nonbonded_force = forces.find_forces(test_system.system, openmm.NonbondedForce, only_one=True) + nonbonded_method = nonbonded_force.getNonbondedMethod() + + # Create all combinations of annihilate_sterics/electrostatics. + for annihilate_sterics, annihilate_electrostatics in itertools.product((True, False), repeat=2): + # Create new region that we can modify. + for i, test_region in enumerate(test_regions): + test_regions[i] = test_region._replace(annihilate_sterics=annihilate_sterics, + annihilate_electrostatics=annihilate_electrostatics) + + # Create test name. + test_case_name = test_system_name[:] + if annihilate_sterics: + test_case_name += ', annihilated sterics' + if annihilate_electrostatics: + test_case_name += ', annihilated electrostatics' + + # Annihilate bonds and angles every three test_cases. + if n_test_cases % 3 == 0: + for i, test_region in enumerate(test_regions): + test_regions[i] = test_region._replace(alchemical_bonds=True, alchemical_angles=True, + alchemical_torsions=True) + test_case_name += ', annihilated bonds, angles and torsions' + + # Add different softcore parameters every five test_cases. + if n_test_cases % 5 == 0: + for i, test_region in enumerate(test_regions): + test_regions[i] = test_region._replace(softcore_alpha=1.0, softcore_beta=1.0, softcore_a=1.0, softcore_b=1.0, + softcore_c=1.0, softcore_d=1.0, softcore_e=1.0, softcore_f=1.0) + test_case_name += ', modified softcore parameters' + + #region_interactions = frozenset(itertools.combinations(range(len(test_regions)), 2)) + # Pre-generate alchemical system. + alchemical_system = direct_space_factory.create_alchemical_system(test_system.system, alchemical_regions = test_regions) + + # Add test case. + cls.test_cases[test_case_name] = (test_system, alchemical_system, test_regions) + + n_test_cases += 1 + + # If we don't use softcore electrostatics and we annihilate charges + # we can test also exact PME treatment. We don't increase n_test_cases + # purposely to keep track of which tests are added above. + if (test_regions[1].softcore_beta == 0.0 and annihilate_electrostatics and + nonbonded_method in [openmm.NonbondedForce.PME, openmm.NonbondedForce.Ewald]): + alchemical_system = exact_pme_factory.create_alchemical_system(test_system.system, alchemical_regions = test_regions) + test_case_name += ', exact PME' + cls.test_cases[test_case_name] = (test_system, alchemical_system, test_regions) + + # If the test system uses reaction field replace reaction field + # of the reference system to allow comparisons. + if nonbonded_method == openmm.NonbondedForce.CutoffPeriodic: + forcefactories.replace_reaction_field(test_system.system, return_copy=False, + switch_width=direct_space_factory.switch_width) + + def test_split_force_groups(self): + """Forces having different lambda variables should have a different force group.""" + # Select 1 implicit, 1 explicit, and 1 exact PME explicit test case randomly. + test_cases = self.filter_cases(lambda x: 'Implicit' in x, max_number=1) + test_cases.update(self.filter_cases(lambda x: 'Explicit ' in x and 'exact PME' in x, max_number=1)) + test_cases.update(self.filter_cases(lambda x: 'Explicit ' in x and 'exact PME' not in x, max_number=1)) + for test_name, (test_system, alchemical_system, alchemical_region) in test_cases.items(): + region_names = [] + for region in alchemical_region: + region_names.append(region.name) + f = partial(check_split_force_groups, alchemical_system, region_names) + f.description = "Testing force splitting among groups of {}".format(test_name) + yield f + + def test_noninteracting_energy_components(self): + """Check all forces annihilated/decoupled when their lambda variables are zero.""" + for test_name, (test_system, alchemical_system, alchemical_region) in self.test_cases.items(): + f = partial(check_multi_noninteracting_energy_components, test_system.system, alchemical_system, + alchemical_region, test_system.positions) + f.description = "Testing non-interacting energy of {}".format(test_name) + yield f + + @attr('slow') + def test_platforms(self): + """Test interacting and noninteracting energies on all platforms.""" + global GLOBAL_ALCHEMY_PLATFORM + old_global_platform = GLOBAL_ALCHEMY_PLATFORM + + # Do not repeat tests on the platform already tested. + if old_global_platform is None: + default_platform_name = utils.get_fastest_platform().getName() + else: + default_platform_name = old_global_platform.getName() + platforms = [platform for platform in utils.get_available_platforms() + if platform.getName() != default_platform_name] + + # Test interacting and noninteracting energies on all platforms. + for platform in platforms: + GLOBAL_ALCHEMY_PLATFORM = platform + for test_name, (test_system, alchemical_system, alchemical_region) in self.test_cases.items(): + f = partial(compare_system_energies, test_system.system, alchemical_system, + alchemical_region, test_system.positions) + f.description = "Test fully interacting energy of {} on {}".format(test_name, platform.getName()) + yield f + f = partial(check_multi_noninteracting_energy_components, test_system.system, alchemical_system, + alchemical_region, test_system.positions) + f.description = "Test non-interacting energy of {} on {}".format(test_name, platform.getName()) + yield f + + # Restore global platform + GLOBAL_ALCHEMY_PLATFORM = old_global_platform + + @attr('slow') + def test_fully_interacting_energy_components(self): + """Test interacting state energy by force component.""" + # This is a very expensive but very informative test. We can + # run this locally when test_fully_interacting_energies() fails. + test_cases = self.filter_cases(lambda x: 'Explicit' in x) + for test_name, (test_system, alchemical_system, alchemical_region) in test_cases.items(): + f = partial(check_multi_interacting_energy_components, test_system.system, alchemical_system, + alchemical_region, test_system.positions) + f.description = "Testing energy components of %s..." % test_name + yield f + class TestDispersionlessAlchemicalFactory(object): """ @@ -1715,12 +2011,14 @@ def test_apply_to_context(self): context = self.full_alanine_state.create_context(copy.deepcopy(integrator)) with nose.tools.assert_raises(AlchemicalStateError): alchemical_state.apply_to_context(context) + del context # Raise error if AlchemicalState is applied to a Context with missing parameters. alchemical_state = AlchemicalState.from_system(self.full_alanine_state.system) context = self.alanine_state.create_context(copy.deepcopy(integrator)) with nose.tools.assert_raises(AlchemicalStateError): alchemical_state.apply_to_context(context) + del context # Correctly sets Context's parameters. for state in [self.full_alanine_state, self.alanine_state_exact_pme]: diff --git a/openmmtools/tests/test_cache.py b/openmmtools/tests/test_cache.py index bc74fa2f8..7fbe4ce3b 100644 --- a/openmmtools/tests/test_cache.py +++ b/openmmtools/tests/test_cache.py @@ -357,3 +357,69 @@ def test_platform_property(self): cache.get_context(self.compatible_states[0], integrator) with nose.tools.assert_raises(RuntimeError): cache.platform = platforms[0] + + def test_platform_properties(self): + # Failure tests + # no platform specified + platform_properties = {"CpuThreads": "2"} + with nose.tools.assert_raises(ValueError) as cm: + ContextCache(platform=None, platform_properties=platform_properties) + # non-string value in properties + cpu_platform = openmm.Platform.getPlatformByName("CPU") + ref_platform = openmm.Platform.getPlatformByName("Reference") + with nose.tools.assert_raises(ValueError) as cm: + ContextCache(platform=cpu_platform, platform_properties={"CpuThreads": 2}) + assert "All platform properties must be strings." in str(cm.exception) + # non-dict properties + with nose.tools.assert_raises(ValueError) as cm: + ContextCache(platform=cpu_platform, platform_properties="jambalaya") + assert str(cm.exception) == "platform_properties must be a dictionary" + # invalid property + with nose.tools.assert_raises(ValueError) as cm: + ContextCache(platform=cpu_platform, platform_properties={"jambalaya": "2"}) + assert "Invalid platform property for this platform." in str(cm.exception) + + # setter + cache = ContextCache( + platform=cpu_platform, + platform_properties=platform_properties + ) + with nose.tools.assert_raises(ValueError) as cm: + cache.platform = ref_platform + assert "Invalid platform property for this platform." in str(cm.exception) + # this should work + cache.set_platform(ref_platform) + assert cache.platform == ref_platform + # assert errors are checked in set_platform + with nose.tools.assert_raises(ValueError) as cm: + cache.set_platform(cpu_platform, platform_properties={"jambalaya": "2"}) + assert "Invalid platform property for this platform." in str(cm.exception) + # assert that resetting the platform resets the properties + cache = ContextCache( + platform=cpu_platform, + platform_properties=platform_properties + ) + cache.platform = None + assert cache._platform_properties is None + + # Functionality test + cache = ContextCache( + platform=cpu_platform, + platform_properties=platform_properties + ) + thermodynamic_state = copy.deepcopy(self.water_300k) + integrator = integrators.LangevinIntegrator(temperature=300 * unit.kelvin, measure_heat=True, + measure_shadow_work=True) + context, _ = cache.get_context(thermodynamic_state, integrator) + assert context.getPlatform().getPropertyValue(context, "CpuThreads") == "2" + + # test serialization + cache.__setstate__(cache.__getstate__()) + assert cache._platform_properties == {"CpuThreads": "2"} + + # test serialization no 2 + state = cache.__getstate__() + state["platform_properties"] = {"CpuThreads": "3"} + cache.__setstate__(state) + assert cache._platform_properties == {"CpuThreads": "3"} + del context diff --git a/openmmtools/tests/test_integrators.py b/openmmtools/tests/test_integrators.py index 01539b327..c1da9b249 100755 --- a/openmmtools/tests/test_integrators.py +++ b/openmmtools/tests/test_integrators.py @@ -759,9 +759,9 @@ def run_alchemical_langevin_integrator(nsteps=0, splitting="O { V R H R V } O"): # Check final conditions before reset current_lambda = nonequilibrium_integrator.getGlobalVariableByName('lambda') - assert current_lambda == 1.0, 'final lambda should be 1.0 (was %f)' % current_lambda + assert current_lambda == 1.0, 'final lambda should be 1.0 (was %f) for splitting %s' % (current_lambda, splitting) current_step = nonequilibrium_integrator.getGlobalVariableByName('step') - assert int(current_step) == max(1,nsteps), 'final step should be %d (was %f)' % (max(1,nsteps), current_step) + assert int(current_step) == max(1,nsteps), 'final step should be %d (was %f) for splitting %s' % (max(1,nsteps), current_step, splitting) nonequilibrium_integrator.reset() # Clean up @@ -774,10 +774,162 @@ def run_alchemical_langevin_integrator(nsteps=0, splitting="O { V R H R V } O"): if nsigma > NSIGMA_MAX: raise Exception("The free energy difference for the nonequilibrium switching for splitting '%s' and %d steps is not zero within statistical error." % (splitting, nsteps)) +def test_periodic_langevin_integrator(splitting="H V R O R V H", ncycles=40, nsteps_neq=1000, nsteps_eq=1000, write_trajectory=False): + """ + Test PeriodicNonequilibriumIntegrator + + Parameters + ---------- + integrator_flavor : openmmtools.integrator.PeriodicNonequilibriumIntegrator (or subclass) + integrator to run + ncycles : int, optional, default=40 + number of cycles + nsteps_neq : int, optional, default=1000 + number of forward/backward annealing steps + nsteps_eq : int, optional, default=1000 + number of equilibration steps to run at endstates before annealing + write_trajectory : bool, optional, default=True + If True, will generate a PDB file that contains the harmonic oscillator trajectory + """ + #max deviation from the calculated free energy + NSIGMA_MAX = 6 + + # These are the alchemical functions that will be used to control the system + temperature = 298.0 * unit.kelvin + sigma = 1.0 * unit.angstrom # stddev of harmonic oscillator + kT = kB * temperature # thermal energy + beta = 1.0 / kT # inverse thermal energy + K = kT / sigma**2 # spring constant corresponding to sigma + mass = 39.948 * unit.amu + period = unit.sqrt(mass/K) # period of harmonic oscillator + timestep = period / 20.0 + collision_rate = 1.0 / period + dF_analytical = 5.0 + parameters = dict() + displacement = 10 * sigma + parameters['testsystems_HarmonicOscillator_x0'] = (0 * sigma, displacement) + parameters['testsystems_HarmonicOscillator_U0'] = (0 * kT, 5 * kT) + integrator_kwargs = {'temperature':temperature, + 'collision_rate': collision_rate, + 'timestep': timestep, + 'measure_shadow_work': False, + 'measure_heat': False} + alchemical_functions = { name : '(1-lambda)*%f + lambda*%f' % (value[0].value_in_unit_system(unit.md_unit_system), value[1].value_in_unit_system(unit.md_unit_system)) for (name, value) in parameters.items() } + # Create harmonic oscillator testsystem + testsystem = testsystems.HarmonicOscillator(K=K, mass=mass) + system = testsystem.system + positions = testsystem.positions + topology = testsystem.topology + + # Create integrator + from openmmtools.integrators import PeriodicNonequilibriumIntegrator + integrator = PeriodicNonequilibriumIntegrator(alchemical_functions=alchemical_functions, + splitting=splitting, + nsteps_eq=nsteps_eq, + nsteps_neq=nsteps_neq, + **integrator_kwargs) + platform = openmm.Platform.getPlatformByName("Reference") + context = openmm.Context(system, integrator, platform) + context.setPositions(positions) + + nsteps_per_cycle = nsteps_eq + nsteps_neq + nsteps_eq + nsteps_neq + assert integrator.getGlobalVariableByName("n_steps_per_cycle") == nsteps_per_cycle + + if write_trajectory: + from simtk.openmm.app import PDBFile + filename = 'neq-trajectory.pdb' + print(f'Writing trajectory to {filename}') + with open(filename, 'wt') as outfile: + # Write reference + import copy + pos1 = copy.deepcopy(positions) + pos2 = copy.deepcopy(positions) + pos2[0,0] += displacement + PDBFile.writeModel(topology, pos1, outfile) + PDBFile.writeModel(topology, pos2, outfile) + + interval = 10 + PDBFile.writeModel(topology, positions, outfile, modelIndex=0) + for step in range(0,2*nsteps_per_cycle,interval): + integrator.step(interval) + positions = context.getState(getPositions=True).getPositions(asNumpy=True) + PDBFile.writeModel(topology, positions, outfile, modelIndex=step) + + PDBFile.writeModel(topology, pos1, outfile) + PDBFile.writeModel(topology, pos2, outfile) + + # Reset the integrator + integrator.reset() + + step = 0 + for cycle in range(2): + # eq (0) + for i in range(nsteps_eq): + integrator.step(1) + step += 1 + assert integrator.getGlobalVariableByName("step") == (step % nsteps_per_cycle) + assert np.isclose(integrator.getGlobalVariableByName("lambda"), 0.0) + # neq (0 -> 1) + for i in range(nsteps_neq): + integrator.step(1) + step += 1 + assert integrator.getGlobalVariableByName("step") == (step % nsteps_per_cycle) + assert np.isclose(integrator.getGlobalVariableByName("lambda"), (i+1)/nsteps_neq), f'{step} {integrator.getGlobalVariableByName("lambda")}' + # eq (1) + for i in range(nsteps_eq): + integrator.step(1) + step += 1 + assert integrator.getGlobalVariableByName("step") == (step % nsteps_per_cycle) + assert np.isclose(integrator.getGlobalVariableByName("lambda"), 1.0) + # neq (1 -> 0) + for i in range(nsteps_neq): + integrator.step(1) + step += 1 + assert integrator.getGlobalVariableByName("step") == (step % nsteps_per_cycle) + assert np.isclose(integrator.getGlobalVariableByName("lambda"), 1 - (i+1)/nsteps_neq) + + assert np.isclose(integrator.getGlobalVariableByName("lambda"), 0.0) + + # Reset the integrator + integrator.reset() + + forward_works, reverse_works = list(), list() + for _ in range(ncycles): + # Equilibrium (lambda = 0) + integrator.step(nsteps_eq) + # Forward (0 -> 1) + initial_work = integrator.get_protocol_work(dimensionless=True) + integrator.step(nsteps_neq) + final_work = integrator.get_protocol_work(dimensionless=True) + forward_work = final_work - initial_work + forward_works.append(forward_work) + # Equilibrium (lambda = 1) + integrator.step(nsteps_eq) + # Reverse work (1 -> 0) + initial_work = integrator.get_protocol_work(dimensionless=True) + integrator.step(nsteps_neq) + final_work = integrator.get_protocol_work(dimensionless=True) + reverse_work = final_work - initial_work + reverse_works.append(reverse_work) + + print(np.array(forward_works).std()) + print(np.array(reverse_works).std()) + + dF, ddF = pymbar.BAR(np.array(forward_works), np.array(reverse_works)) + nsigma = np.abs(dF - dF_analytical) / ddF + assert np.isclose(integrator.getGlobalVariableByName("lambda"), 0.0) + print("analytical DeltaF: {:12.4f}, DeltaF: {:12.4f}, dDeltaF: {:12.4f}, nsigma: {:12.1f}".format(dF_analytical, dF, ddF, nsigma)) + if nsigma > NSIGMA_MAX: + raise Exception(f"The free energy difference for the nonequilibrium switching for splitting {splitting} is not zero within statistical error.") + + # Clean up + del context + del integrator + def test_alchemical_langevin_integrator(): - for splitting in ["O { V R H R V } O", "O V R H R V O", "H R V O V R H"]: + for splitting in ["O V R H R V O", "H R V O V R H", "O { V R H R V } O"]: for nsteps in [0, 1, 10]: - run_alchemical_langevin_integrator(nsteps=nsteps) + run_alchemical_langevin_integrator(splitting=splitting, nsteps=nsteps) if __name__=="__main__": test_alchemical_langevin_integrator() diff --git a/openmmtools/tests/test_sampling.py b/openmmtools/tests/test_sampling.py index d13d0cfb2..6a3b8486f 100644 --- a/openmmtools/tests/test_sampling.py +++ b/openmmtools/tests/test_sampling.py @@ -23,17 +23,20 @@ from io import StringIO import numpy as np -import openmmtools as mmtools import scipy.integrate import yaml from nose.plugins.attrib import attr from nose.tools import assert_raises -from openmmtools import testsystems from simtk import openmm, unit - import mpiplus -from openmmtools.multistate import MultiStateReporter, MultiStateSampler, ReplicaExchangeSampler, ParallelTemperingSampler, SAMSSampler -from openmmtools.multistate import ReplicaExchangeAnalyzer, SAMSAnalyzer + +import openmmtools as mmtools +from openmmtools import testsystems +from openmmtools.multistate import MultiStateReporter +from openmmtools.multistate import MultiStateSampler, MultiStateSamplerAnalyzer +from openmmtools.multistate import ReplicaExchangeSampler, ReplicaExchangeAnalyzer +from openmmtools.multistate import ParallelTemperingSampler, ParallelTemperingAnalyzer +from openmmtools.multistate import SAMSSampler, SAMSAnalyzer from openmmtools.multistate.multistatereporter import _DictYamlLoader # quiet down some citation spam @@ -64,289 +67,162 @@ def check_thermodynamic_states_equality(original_states, restored_states): assert original_state.lambda_sterics == restored_state.lambda_sterics assert original_state.lambda_electrostatics == restored_state.lambda_electrostatics +# ============================================================================== +# Harmonic oscillator free energy test +# ============================================================================== -def compute_harmonic_oscillator_expectations(K, temperature): - """Compute mean and variance of potential and kinetic energies for a 3D harmonic oscillator. - - Notes - ----- - Numerical quadrature is used to compute the mean and standard deviation of the potential energy. - Mean and standard deviation of the kinetic energy, as well as the absolute free energy, is computed analytically. - - Parameters - ---------- - K : simtk.unit.Quantity - Spring constant. - temperature : simtk.unit.Quantity - Temperature. - - Returns - ------- - values : dict - - TODO - - Replace this with built-in analytical expectations - - """ - - values = dict() +class TestHarmonicOscillatorsMultiStateSampler(object): + """Test multistate sampler can compute free energies of harmonic oscillator""" - # Compute thermal energy and inverse temperature from specified temperature. - kB = unit.BOLTZMANN_CONSTANT_kB * unit.AVOGADRO_CONSTANT_NA - kT = kB * temperature # thermal energy - beta = 1.0 / kT # inverse temperature + # ------------------------------------ + # VARIABLES TO SET FOR EACH TEST CLASS + # ------------------------------------ - # Compute standard deviation along one dimension. - sigma = 1.0 / unit.sqrt(beta * K) + N_SAMPLERS = 3 + N_STATES = 5 # number of thermodynamic states to sample; two additional unsampled states will be added + N_ITERATIONS = 500 # number of iterations + SAMPLER = MultiStateSampler + ANALYZER = MultiStateSamplerAnalyzer - # Define limits of integration along r. - r_min = 0.0 * unit.nanometers # initial value for integration - r_max = 10.0 * sigma # maximum radius to integrate to + @classmethod + def setup_class(cls): + # Configure the global context cache to use the Reference platform + from openmmtools import cache + platform = openmm.Platform.getPlatformByName('Reference') + cls.old_global_context_cache = cache.global_context_cache + cache.global_context_cache = cache.ContextCache(platform=platform) - # Compute mean and std dev of potential energy. - V = lambda r : (K/2.0) * (r*unit.nanometers)**2 / unit.kilojoules_per_mole # potential in kJ/mol, where r in nm - q = lambda r : 4.0 * math.pi * r**2 * math.exp(-beta * (K/2.0) * (r*unit.nanometers)**2) # q(r), where r in nm - (IqV2, dIqV2) = scipy.integrate.quad(lambda r : q(r) * V(r)**2, r_min / unit.nanometers, r_max / unit.nanometers) - (IqV, dIqV) = scipy.integrate.quad(lambda r : q(r) * V(r), r_min / unit.nanometers, r_max / unit.nanometers) - (Iq, dIq) = scipy.integrate.quad(lambda r : q(r), r_min / unit.nanometers, r_max / unit.nanometers) - values['potential'] = dict() - values['potential']['mean'] = (IqV / Iq) * unit.kilojoules_per_mole - values['potential']['stddev'] = (IqV2 / Iq) * unit.kilojoules_per_mole + # Set oscillators to mass of carbon atom + mass = 12.0 * unit.amu - # Compute mean and std dev of kinetic energy. - values['kinetic'] = dict() - values['kinetic']['mean'] = (3./2.) * kT - values['kinetic']['stddev'] = math.sqrt(3./2.) * kT + # Translate the sampler states to be different one from each other. + n_particles = 1 + positions = unit.Quantity(np.zeros([n_particles,3]), unit.angstroms) + cls.sampler_states = [ + mmtools.states.SamplerState(positions=positions) + for sampler_index in range(cls.N_SAMPLERS)] + + # Generate list of thermodynamic states and analytical free energies + # This list includes both sampled and two unsampled states + thermodynamic_states = list() + temperature = 300 * unit.kelvin + f_i = np.zeros([cls.N_STATES+2]) # f_i[state_index] is the dimensionless free energy of state `state_index` + for state_index in range(cls.N_STATES + 2): + sigma = (1.0 + 0.2 * state_index) * unit.angstroms # compute reasonable standard deviation with good overlap + kT = kB * temperature # compute thermal energy + K = kT / sigma**2 # compute spring constant + testsystem = testsystems.HarmonicOscillator(K=K, mass=mass) + thermodynamic_state = mmtools.states.ThermodynamicState(testsystem.system, temperature) + thermodynamic_states.append(thermodynamic_state) + + # Store analytical reduced free energy + f_i[state_index] = - np.log(2 * np.pi * (sigma / unit.angstroms)**2) * (3.0/2.0) + + # delta_f_ij_analytical[i,j] = f_i_analytical[j] - f_i_analytical[i] + cls.f_i_analytical = f_i + cls.delta_f_ij_analytical = f_i - f_i[:,np.newaxis] + + # Define sampled and unsampled states. + cls.nstates = cls.N_STATES + cls.unsampled_states = [thermodynamic_states[0], thermodynamic_states[-1]] # first and last + cls.thermodynamic_states = thermodynamic_states[1:-1] # intermediate states - # Compute dimensionless free energy. - # f = - \ln \int_{-\infty}^{+\infty} \exp[-\beta K x^2 / 2] - # = - \ln \int_{-\infty}^{+\infty} \exp[-x^2 / 2 \sigma^2] - # = - \ln [\sqrt{2 \pi} \sigma] - values['f'] = - np.log(2 * np.pi * (sigma / unit.angstroms)**2) * (3.0/2.0) + @classmethod + def teardown_class(cls): + # Restore global context cache + from openmmtools import cache + cache.global_context_cache = cls.old_global_context_cache + + def run(self, include_unsampled_states=False): + # Create and configure simulation object + move = mmtools.mcmc.MCDisplacementMove(displacement_sigma=1.0*unit.angstroms) + simulation = self.SAMPLER(mcmc_moves=move, number_of_iterations=self.N_ITERATIONS) + + # Define file for temporary storage. + with mmtools.utils.temporary_directory() as tmp_dir: + storage = os.path.join(tmp_dir, 'test_storage.nc') + reporter = MultiStateReporter(storage, checkpoint_interval=self.N_ITERATIONS) + + if include_unsampled_states: + simulation.create(self.thermodynamic_states, self.sampler_states, reporter, + unsampled_thermodynamic_states=self.unsampled_states) + else: + simulation.create(self.thermodynamic_states, self.sampler_states, reporter) - return values + # Run simulation without debug logging + import logging + logger = logging.getLogger() + logger.setLevel(logging.CRITICAL) + simulation.run() + # Create Analyzer. + analyzer = self.ANALYZER(reporter) -# ============================================================================== -# TEST ANALYSIS REPLICA EXCHANGE -# ============================================================================== + # Check if free energies have the right shape and deviations exceed tolerance + delta_f_ij, delta_f_ij_stderr = analyzer.get_free_energy() + nstates, _ = delta_f_ij.shape -@attr('slow') # Skip on Travis-CI -def test_replica_exchange_harmonic_oscillator(verbose=False, verbose_simulation=False): - """Test harmonic oscillator free energies for replica-exchange.""" - # Define mass of carbon atom. - mass = 12.0 * unit.amu - - sampler_states = list() - thermodynamic_states = list() - analytical_results = list() - f_i_analytical = list() # Dimensionless free energies. - u_i_analytical = list() # Reduced potentials. - - # Define thermodynamic states. - Ks = [500.00, 400.0, 300.0] * unit.kilocalories_per_mole / unit.angstroms**2 # Spring constants. - temperatures = [300.0, 350.0, 400.0] * unit.kelvin # Temperatures. - for (K, temperature) in zip(Ks, temperatures): - # Create harmonic oscillator system. - testsystem = testsystems.HarmonicOscillator(K=K, mass=mass, mm=openmm) - - # Create thermodynamic state and save positions. - system, positions = [testsystem.system, testsystem.positions] - sampler_states.append(mmtools.states.SamplerState(positions)) - thermodynamic_states.append(mmtools.states.ThermodynamicState(system=system, temperature=temperature)) - - # Store analytical results. - results = compute_harmonic_oscillator_expectations(K, temperature) - analytical_results.append(results) - f_i_analytical.append(results['f']) - reduced_potential = results['potential']['mean'] / (kB * temperature) - u_i_analytical.append(reduced_potential) - - # Compute analytical Delta_f_ij - nstates = len(f_i_analytical) - f_i_analytical = np.array(f_i_analytical) - u_i_analytical = np.array(u_i_analytical) - s_i_analytical = u_i_analytical - f_i_analytical - Delta_f_ij_analytical = np.zeros([nstates, nstates], np.float64) - Delta_u_ij_analytical = np.zeros([nstates, nstates], np.float64) - Delta_s_ij_analytical = np.zeros([nstates, nstates], np.float64) - for i in range(nstates): - for j in range(nstates): - Delta_f_ij_analytical[i, j] = f_i_analytical[j] - f_i_analytical[i] - Delta_u_ij_analytical[i, j] = u_i_analytical[j] - u_i_analytical[i] - Delta_s_ij_analytical[i, j] = s_i_analytical[j] - s_i_analytical[i] - - # Create and configure simulation object. - move = mmtools.mcmc.LangevinDynamicsMove(timestep=2.0*unit.femtoseconds, - collision_rate=20.0/unit.picosecond, - n_steps=500, reassign_velocities=True) - simulation = ReplicaExchangeSampler(mcmc_moves=move, number_of_iterations=400) - - # Define file for temporary storage. - with mmtools.utils.temporary_directory() as tmp_dir: - storage = os.path.join(tmp_dir, 'test_storage.nc') - reporter = MultiStateReporter(storage, checkpoint_interval=1) - simulation.create(thermodynamic_states, sampler_states, reporter) - - # Run simulation we keep the debug info off during the simulation - # to not clog the output, and reactivate it for analysis. - simulation.run() - - # Create Analyzer. - analyzer = ReplicaExchangeAnalyzer(reporter) - - # TODO: Check if deviations exceed tolerance. - Delta_f_ij, dDelta_f_ij = analyzer.get_free_energy() - error = np.abs(Delta_f_ij - Delta_f_ij_analytical) - indices = np.where(dDelta_f_ij > 0.0) - nsigma = np.zeros([nstates,nstates], np.float32) - nsigma[indices] = error[indices] / dDelta_f_ij[indices] - MAX_SIGMA = 6.0 # maximum allowed number of standard errors - if np.any(nsigma > MAX_SIGMA): - print("Delta_f_ij") - print(Delta_f_ij) - print("Delta_f_ij_analytical") - print(Delta_f_ij_analytical) - print("error") - print(error) - print("stderr") - print(dDelta_f_ij) - print("nsigma") - print(nsigma) - raise Exception("Dimensionless free energy difference exceeds MAX_SIGMA of %.1f" % MAX_SIGMA) - - Delta_u_ij, dDelta_u_ij = analyzer.get_enthalpy() - error = Delta_u_ij - Delta_u_ij_analytical - nsigma = np.zeros([nstates,nstates], np.float32) - nsigma[indices] = error[indices] / dDelta_f_ij[indices] - if np.any(nsigma > MAX_SIGMA): - print("Delta_u_ij") - print(Delta_u_ij) - print("Delta_u_ij_analytical") - print(Delta_u_ij_analytical) - print("error") - print(error) - print("nsigma") - print(nsigma) - raise Exception("Dimensionless potential energy difference exceeds MAX_SIGMA of %.1f" % MAX_SIGMA) + if include_unsampled_states: + nstates_expected = self.N_STATES+2 # We expect N_STATES plus two additional states + delta_f_ij_analytical = self.delta_f_ij_analytical # Use the whole matrix + else: + nstates_expected = self.N_STATES # We expect only N_STATES + delta_f_ij_analytical = self.delta_f_ij_analytical[1:-1,1:-1] # Use only the intermediate, sampled states + + assert nstates == nstates_expected, \ + f'analyzer.get_free_energy() returned {delta_f_ij.shape} but expected {nstates_expected,nstates_expected}' + + error = np.abs(delta_f_ij - delta_f_ij_analytical) + indices = np.where(delta_f_ij_stderr > 0.0) + nsigma = np.zeros([nstates,nstates], np.float32) + nsigma[indices] = error[indices] / delta_f_ij_stderr[indices] + MAX_SIGMA = 6.0 # maximum allowed number of standard errors + if np.any(nsigma > MAX_SIGMA): + np.set_printoptions(precision=3) + print("delta_f_ij") + print(delta_f_ij) + print("delta_f_ij_analytical") + print(delta_f_ij_analytical) + print("error") + print(error) + print("stderr") + print(delta_f_ij_stderr) + print("nsigma") + print(nsigma) + raise Exception("Dimensionless free energy difference exceeds MAX_SIGMA of %.1f" % MAX_SIGMA) # Clean up. del simulation - if verbose: - print("PASSED.") + def test_with_unsampled_states(self): + self.run(include_unsampled_states=True) + def test_without_unsampled_states(self): + self.run(include_unsampled_states=False) -# ============================================================================== -# TEST ANALYSIS SAMS -# ============================================================================== +class TestHarmonicOscillatorsReplicaExchangeSampler(TestHarmonicOscillatorsMultiStateSampler): + """Test replica-exchange sampler can compute free energies of harmonic oscillator""" -@attr('slow') # Skip on Travis-CI -def test_sams_harmonic_oscillator(verbose=False, verbose_simulation=False): - """Harmonic oscillator free energies for SAMS.""" - # Define mass of carbon atom. - mass = 12.0 * unit.amu - - sampler_states = list() - thermodynamic_states = list() - analytical_results = list() - f_i_analytical = list() # Dimensionless free energies. - u_i_analytical = list() # Reduced potentials. - - # Define thermodynamic states. - Ks = [500.00, 400.0, 300.0] * unit.kilocalories_per_mole / unit.angstroms**2 # Spring constants. - temperatures = [300.0, 350.0, 400.0] * unit.kelvin # Temperatures. - for (K, temperature) in zip(Ks, temperatures): - # Create harmonic oscillator system. - testsystem = testsystems.HarmonicOscillator(K=K, mass=mass, mm=openmm) - - # Create thermodynamic state and save positions. - system, positions = [testsystem.system, testsystem.positions] - sampler_states.append(mmtools.states.SamplerState(positions)) - thermodynamic_states.append(mmtools.states.ThermodynamicState(system=system, temperature=temperature)) - - # Store analytical results. - results = compute_harmonic_oscillator_expectations(K, temperature) - analytical_results.append(results) - f_i_analytical.append(results['f']) - reduced_potential = results['potential']['mean'] / (kB * temperature) - u_i_analytical.append(reduced_potential) - - # Compute analytical Delta_f_ij - nstates = len(f_i_analytical) - f_i_analytical = np.array(f_i_analytical) - u_i_analytical = np.array(u_i_analytical) - s_i_analytical = u_i_analytical - f_i_analytical - Delta_f_ij_analytical = np.zeros([nstates, nstates], np.float64) - Delta_u_ij_analytical = np.zeros([nstates, nstates], np.float64) - Delta_s_ij_analytical = np.zeros([nstates, nstates], np.float64) - for i in range(nstates): - for j in range(nstates): - Delta_f_ij_analytical[i, j] = f_i_analytical[j] - f_i_analytical[i] - Delta_u_ij_analytical[i, j] = u_i_analytical[j] - u_i_analytical[i] - Delta_s_ij_analytical[i, j] = s_i_analytical[j] - s_i_analytical[i] - - # Create and configure simulation object. - move = mmtools.mcmc.LangevinDynamicsMove(timestep=2.0*unit.femtoseconds, - collision_rate=20.0/unit.picosecond, - n_steps=500, reassign_velocities=True) - simulation = SAMSSampler(mcmc_moves=move, number_of_iterations=200) - - # Define file for temporary storage. - with mmtools.utils.temporary_directory() as tmp_dir: - storage = os.path.join(tmp_dir, 'test_storage.nc') - reporter = MultiStateReporter(storage, checkpoint_interval=1) - simulation.create(thermodynamic_states, sampler_states, reporter) - - # Run simulation we keep the debug info off during the simulation - # to not clog the output, and reactivate it for analysis. - simulation.run() - - # Create Analyzer. - analyzer = SAMSAnalyzer(reporter) - - # TODO: Check if deviations exceed tolerance. - Delta_f_ij, dDelta_f_ij = analyzer.get_free_energy() - error = np.abs(Delta_f_ij - Delta_f_ij_analytical) - indices = np.where(dDelta_f_ij > 0.0) - nsigma = np.zeros([nstates,nstates], np.float32) - nsigma[indices] = error[indices] / dDelta_f_ij[indices] - MAX_SIGMA = 6.0 # maximum allowed number of standard errors - if np.any(nsigma > MAX_SIGMA): - print("Delta_f_ij") - print(Delta_f_ij) - print("Delta_f_ij_analytical") - print(Delta_f_ij_analytical) - print("error") - print(error) - print("stderr") - print(dDelta_f_ij) - print("nsigma") - print(nsigma) - raise Exception("Dimensionless free energy difference exceeds MAX_SIGMA of %.1f" % MAX_SIGMA) - - Delta_u_ij, dDelta_u_ij = analyzer.get_enthalpy() - error = Delta_u_ij - Delta_u_ij_analytical - nsigma = np.zeros([nstates,nstates], np.float32) - nsigma[indices] = error[indices] / dDelta_f_ij[indices] - if np.any(nsigma > MAX_SIGMA): - print("Delta_u_ij") - print(Delta_u_ij) - print("Delta_u_ij_analytical") - print(Delta_u_ij_analytical) - print("error") - print(error) - print("nsigma") - print(nsigma) - raise Exception("Dimensionless potential energy difference exceeds MAX_SIGMA of %.1f" % MAX_SIGMA) + # ------------------------------------ + # VARIABLES TO SET FOR EACH TEST CLASS + # ------------------------------------ - # Clean up. - del simulation + N_SAMPLERS = 5 + N_STATES = 5 + SAMPLER = ReplicaExchangeSampler + ANALYZER = ReplicaExchangeAnalyzer - if verbose: - print("PASSED.") +class TestHarmonicOscillatorsSAMSSampler(TestHarmonicOscillatorsMultiStateSampler): + """Test SAMS sampler can compute free energies of harmonic oscillator""" + + # ------------------------------------ + # VARIABLES TO SET FOR EACH TEST CLASS + # ------------------------------------ + N_SAMPLERS = 1 + N_STATES = 5 + SAMPLER = SAMSSampler + ANALYZER = SAMSAnalyzer # ============================================================================== # TEST REPORTER @@ -687,7 +563,8 @@ def call_sampler_create(cls, sampler, reporter, unsampled_states): """Helper function to call the create method for the sampler""" # Allows initial thermodynamic states to be handled by the built in methods - sampler.create(thermodynamic_states, sampler_states, reporter, unsampled_thermodynamic_states=unsampled_states) + sampler.create(thermodynamic_states, sampler_states, reporter, + unsampled_thermodynamic_states=unsampled_states) # -------------------------------- # Tests overwritten by sub-classes @@ -1598,6 +1475,113 @@ def test_stored_properties(self): additional_values.update(self.property_creator('replica_mixing_scheme', 'replica_mixing_scheme', None, None)) self.actual_stored_properties_check(additional_properties=additional_values) + @attr('slow') # Skip on Travis-CI + def test_uniform_mixing(self): + """Test that mixing is uniform for a sequence of harmonic oscillators. + + This test was implemented following choderalab/yank#1130. Briefly, when + a repex calculation was distributed over multiple MPI processes, the + odd replicas turned out to be much less diffusive than the even replicas. + + """ + temperature = 300.0 * unit.kelvin + sigma = 1.0 * unit.angstrom # Distance between two oscillators. + n_states = 50 # Number of harmonic oscillators. + + timestep = 2.0 * unit.femtosecond + n_steps = 5 # Number of steps per iteration. + number_of_iterations = 2000 + + # Build an equidistant sequence of harmonic oscillators. + sampler_states = [] + thermodynamic_states = [] + + # The minima of the harmonic oscillators are 1 kT from each other. + k = mmtools.constants.kB * temperature / sigma**2 # Spring constant. + oscillator = testsystems.HarmonicOscillator(K=k) + + for oscillator_idx in range(n_states): + system = copy.deepcopy(oscillator.system) + positions = copy.deepcopy(oscillator.positions) + + # Determine the position of the harmonic oscillator minimum. + minimum_position = oscillator_idx * sigma + minimum_position_unitless = minimum_position.value_in_unit_system(unit.md_unit_system) + positions[0][0] = minimum_position + + # Create an oscillator starting from its minimum. + force = system.getForce(0) + assert force.getGlobalParameterName(1) == 'testsystems_HarmonicOscillator_x0' + force.setGlobalParameterDefaultValue(1, minimum_position_unitless) + + thermodynamic_states.append(mmtools.states.ThermodynamicState( + system=system, temperature=temperature)) + sampler_states.append(mmtools.states.SamplerState(positions)) + + # Run a short repex simulation and gather data. + with self.temporary_storage_path() as storage_path: + # Create and run object. + sampler = self.SAMPLER( + mcmc_moves=mmtools.mcmc.LangevinDynamicsMove(timestep=timestep, n_steps=n_steps), + number_of_iterations=number_of_iterations, + ) + reporter = self.REPORTER(storage_path, checkpoint_interval=number_of_iterations) + sampler.create(thermodynamic_states, sampler_states, reporter) + sampler.run() + + # Retrieve from the reporter the mixing information before deleting. + # Only the reporter from MPI node 0 should be open. + n_accepted_matrix, n_proposed_matrix = mpiplus.run_single_node( + task=reporter.read_mixing_statistics, + rank=0, broadcast_result=True + ) + replica_thermo_states = mpiplus.run_single_node( + task=reporter.read_replica_thermodynamic_states, + rank=0, broadcast_result=True + ) + del sampler, reporter + + # No need to analyze the same data in multiple MPI processes. + mpicomm = mpiplus.get_mpicomm() + if mpicomm is not None and mpicomm.rank == 0: + print('Acceptance matrix') + print(n_accepted_matrix) + print() + + # Count the number of visited states by each replica. + replica_thermo_state_counts = np.empty(n_states) + for replica_idx in range(n_states): + n_visited_states = len(set(replica_thermo_states[:, replica_idx])) + replica_thermo_state_counts[replica_idx] = n_visited_states + print(replica_idx, ':', n_visited_states) + print() + + # Count the number of visited states by each MPI process. + n_mpi_processes = mpicomm.size + mpi_avg_thermo_state_counts = np.empty(n_mpi_processes) + mpi_sem_thermo_state_counts = np.empty(n_mpi_processes) + for mpi_idx in range(n_mpi_processes): + # Find replicas assigned to this MPI process. + replica_indices = list(i for i in range(n_states) if i % n_mpi_processes == mpi_idx) + # Find the average number of states visited by + # the replicas assigned to this MPI process. + mpi_avg_thermo_state_counts[mpi_idx] = np.mean(replica_thermo_state_counts[replica_indices]) + mpi_sem_thermo_state_counts[mpi_idx] = np.std(replica_thermo_state_counts[replica_indices], ddof=1) / np.sqrt(len(replica_indices)) + + # These should be roughly equal. + print('MPI process mean number of thermo states visited:') + for mpi_idx, (mean, sem) in enumerate(zip(mpi_avg_thermo_state_counts, + mpi_sem_thermo_state_counts)): + print('{}: {} +- {}'.format(mpi_idx, mean, 2*sem)) + + # Check if the confidence intervals overlap. + def are_overlapping(interval1, interval2): + return min(interval1[1], interval2[1]) - max(interval1[0], interval2[0]) > 0 + + cis = [(mean-2*sem, mean+2*sem) for mean, sem in zip(mpi_avg_thermo_state_counts, mpi_sem_thermo_state_counts)] + for i in range(1, len(cis)): + assert are_overlapping(cis[0], cis[i]) + class TestSingleReplicaSAMS(TestMultiStateSampler): """Test suite for SAMSSampler class.""" diff --git a/openmmtools/tests/test_states.py b/openmmtools/tests/test_states.py index 008a94a7d..8a92d4da3 100644 --- a/openmmtools/tests/test_states.py +++ b/openmmtools/tests/test_states.py @@ -59,6 +59,8 @@ def setup_class(cls): """Create the test systems used in the test suite.""" cls.std_pressure = ThermodynamicState._STANDARD_PRESSURE cls.std_temperature = ThermodynamicState._STANDARD_TEMPERATURE + cls.std_surface_tension = ThermodynamicState._STANDARD_SURFACE_TENSION + cls.modified_surface_tension = 100.0 * unit.bar * unit.nanometer alanine_explicit = testsystems.AlanineDipeptideExplicit() cls.alanine_positions = alanine_explicit.positions @@ -94,13 +96,37 @@ def setup_class(cls): cls.multiple_barostat_alanine.addForce(barostat) # A system with an unsupported MonteCarloAnisotropicBarostat - cls.unsupported_barostat_alanine = copy.deepcopy(cls.alanine_explicit) + cls.unsupported_anisotropic_barostat_alanine = copy.deepcopy(cls.alanine_explicit) + pressure_in_bars = cls.std_pressure / unit.bar + anisotropic_pressure = openmm.Vec3(pressure_in_bars, pressure_in_bars, + 1.0+pressure_in_bars) + cls.unsupported_anisotropic_barostat = openmm.MonteCarloAnisotropicBarostat(anisotropic_pressure, cls.std_temperature) + cls.unsupported_anisotropic_barostat_alanine.addForce(cls.unsupported_anisotropic_barostat) + + # A system with an unsupported MonteCarloMembraneBarostat + cls.membrane_barostat_alanine_gamma_nonzero = copy.deepcopy(cls.alanine_explicit) + # working around a bug in the unit conversion https://github.com/openmm/openmm/issues/2406 + cls.membrane_barostat_gamma_nonzero = openmm.MonteCarloMembraneBarostat( + cls.std_pressure, cls.modified_surface_tension.value_in_unit(unit.bar*unit.nanometer), cls.std_temperature, + openmm.MonteCarloMembraneBarostat.XYIsotropic, openmm.MonteCarloMembraneBarostat.ZFree + ) + cls.membrane_barostat_alanine_gamma_nonzero.addForce(cls.membrane_barostat_gamma_nonzero) + + # A system with a supported MonteCarloAnisotropicBarostat + cls.supported_anisotropic_barostat_alanine = copy.deepcopy(cls.alanine_explicit) pressure_in_bars = cls.std_pressure / unit.bar anisotropic_pressure = openmm.Vec3(pressure_in_bars, pressure_in_bars, pressure_in_bars) - cls.anisotropic_barostat = openmm.MonteCarloAnisotropicBarostat(anisotropic_pressure, - cls.std_temperature) - cls.unsupported_barostat_alanine.addForce(cls.anisotropic_barostat) + cls.supported_anisotropic_barostat = openmm.MonteCarloAnisotropicBarostat(anisotropic_pressure, cls.std_temperature) + cls.supported_anisotropic_barostat_alanine.addForce(cls.supported_anisotropic_barostat) + + # A system with a supported MonteCarloMembraneBarostat + cls.membrane_barostat_alanine_gamma_zero = copy.deepcopy(cls.alanine_explicit) + cls.membrane_barostat_gamma_zero = openmm.MonteCarloMembraneBarostat( + cls.std_pressure, 0.0, cls.std_temperature, + openmm.MonteCarloMembraneBarostat.XYIsotropic, openmm.MonteCarloMembraneBarostat.ZFree + ) + cls.membrane_barostat_alanine_gamma_zero.addForce(cls.membrane_barostat_gamma_zero) # A system with an inconsistent pressure in the barostat. cls.inconsistent_pressure_alanine = copy.deepcopy(cls.alanine_explicit) @@ -166,10 +192,16 @@ def test_method_find_barostat(self): barostat = ThermodynamicState._find_barostat(self.barostated_alanine) assert isinstance(barostat, openmm.MonteCarloBarostat) + barostat = ThermodynamicState._find_barostat(self.supported_anisotropic_barostat_alanine) + assert isinstance(barostat, openmm.MonteCarloAnisotropicBarostat) + + barostat = ThermodynamicState._find_barostat(self.membrane_barostat_alanine_gamma_zero) + assert isinstance(barostat, openmm.MonteCarloMembraneBarostat) + # Raise exception if multiple or unsupported barostats found TE = ThermodynamicsError # shortcut test_cases = [(self.multiple_barostat_alanine, TE.MULTIPLE_BAROSTATS), - (self.unsupported_barostat_alanine, TE.UNSUPPORTED_BAROSTAT)] + (self.unsupported_anisotropic_barostat_alanine, TE.UNSUPPORTED_ANISOTROPIC_BAROSTAT)] for system, err_code in test_cases: with nose.tools.assert_raises(ThermodynamicsError) as cm: ThermodynamicState._find_barostat(system) @@ -205,6 +237,9 @@ def test_method_is_barostat_consistent(self): barostat = openmm.MonteCarloBarostat(pressure, temperature + 10*unit.kelvin) assert not state._is_barostat_consistent(barostat) + assert not state._is_barostat_consistent(self.supported_anisotropic_barostat) + assert not state._is_barostat_consistent(self.membrane_barostat_gamma_zero) + def test_method_set_system_temperature(self): """ThermodynamicState._set_system_temperature() method.""" system = copy.deepcopy(self.alanine_no_thermostat) @@ -222,29 +257,35 @@ def test_method_set_system_temperature(self): def test_property_temperature(self): """ThermodynamicState.temperature property.""" - state = ThermodynamicState(self.barostated_alanine, - self.std_temperature) - assert state.temperature == self.std_temperature - - temperature = self.std_temperature + 10.0*unit.kelvin - state.temperature = temperature - assert state.temperature == temperature - assert get_barostat_temperature(state.barostat) == temperature - - # Setting temperature to None raise error. - with nose.tools.assert_raises(ThermodynamicsError) as cm: - state.temperature = None - assert cm.exception.code == ThermodynamicsError.NONE_TEMPERATURE + for system in [self.barostated_alanine, + self.supported_anisotropic_barostat_alanine, + self.membrane_barostat_alanine_gamma_zero]: + state = ThermodynamicState(system, + self.std_temperature) + assert state.temperature == self.std_temperature + + temperature = self.std_temperature + 10.0*unit.kelvin + state.temperature = temperature + assert state.temperature == temperature + assert get_barostat_temperature(state.barostat) == temperature + + # Setting temperature to None raise error. + with nose.tools.assert_raises(ThermodynamicsError) as cm: + state.temperature = None + assert cm.exception.code == ThermodynamicsError.NONE_TEMPERATURE def test_method_set_system_pressure(self): """ThermodynamicState._set_system_pressure() method.""" - state = ThermodynamicState(self.alanine_explicit, self.std_temperature) - system = state.system - assert state._find_barostat(system) is None - state._set_system_pressure(system, self.std_pressure) - assert state._find_barostat(system).getDefaultPressure() == self.std_pressure - state._set_system_pressure(system, None) - assert state._find_barostat(system) is None + for system in [self.barostated_alanine, + self.supported_anisotropic_barostat_alanine, + self.membrane_barostat_alanine_gamma_zero]: + state = ThermodynamicState(self.alanine_explicit, self.std_temperature) + system = state.system + assert state._find_barostat(system) is None + state._set_system_pressure(system, self.std_pressure) + assert state._find_barostat(system).getDefaultPressure() == self.std_pressure + state._set_system_pressure(system, None) + assert state._find_barostat(system) is None def test_property_pressure_barostat(self): """ThermodynamicState.pressure and barostat properties.""" @@ -268,11 +309,14 @@ def test_property_pressure_barostat(self): assert state.barostat is None # Correctly reads and set system pressures - periodic_testcases = [self.alanine_explicit] + periodic_testcases = [self.alanine_explicit, + self.supported_anisotropic_barostat_alanine, + self.membrane_barostat_alanine_gamma_zero] for system in periodic_testcases: - state = ThermodynamicState(system, self.std_temperature) - assert state.pressure is None - assert state.barostat is None + if system is self.alanine_explicit: + state = ThermodynamicState(system, self.std_temperature) + assert state.pressure is None + assert state.barostat is None # Setting pressure adds a barostat state.pressure = self.std_pressure @@ -319,12 +363,50 @@ def test_property_pressure_barostat(self): # Assign incompatible barostat raise error with nose.tools.assert_raises(ThermodynamicsError) as cm: - state.barostat = self.anisotropic_barostat - assert cm.exception.code == ThermodynamicsError.UNSUPPORTED_BAROSTAT + state.barostat = self.unsupported_anisotropic_barostat + assert cm.exception.code == ThermodynamicsError.UNSUPPORTED_ANISOTROPIC_BAROSTAT + + # Assign barostat with different type raise error + if state.barostat is not None and type(state.barostat) != type(self.supported_anisotropic_barostat): + with nose.tools.assert_raises(ThermodynamicsError) as cm: + state.barostat = self.supported_anisotropic_barostat + assert cm.exception.code == ThermodynamicsError.INCONSISTENT_BAROSTA + if state.barostat is not None and type(state.barostat) != type(self.membrane_barostat_gamma_zero): + with nose.tools.assert_raises(ThermodynamicsError) as cm: + state.barostat = self.membrane_barostat_gamma_zero + assert cm.exception.code == ThermodynamicsError.INCONSISTENT_BAROSTAT # After exception, state is left consistent assert state.pressure is None + def test_surface_tension(self): + """Test querying and setting surface tension""" + # test setting and getting surface tension for a system without barostat + state = ThermodynamicState(self.alanine_explicit, self.std_temperature) + assert state.surface_tension is None + with nose.tools.assert_raises(ThermodynamicsError) as cm: + state.surface_tension = self.std_surface_tension + assert cm.exception.code == ThermodynamicsError.SURFACE_TENSION_NOT_SUPPORTED + + # test setting and getting surface tension for a system with a non-membrane barostat + state = ThermodynamicState(self.barostated_alanine, self.std_temperature) + assert state.surface_tension is None + with nose.tools.assert_raises(ThermodynamicsError) as cm: + state.surface_tension = self.std_surface_tension + assert cm.exception.code == ThermodynamicsError.SURFACE_TENSION_NOT_SUPPORTED + + # test setting and getting surface tension + state = ThermodynamicState(self.membrane_barostat_alanine_gamma_zero, self.std_temperature) + assert utils.is_quantity_close(state.surface_tension, 0.0 * unit.bar * unit.nanometer, rtol=0.0, atol=1e-10) + state.surface_tension = self.modified_surface_tension + assert utils.is_quantity_close(state.surface_tension, self.modified_surface_tension) + state.surface_tension = 0.0 * unit.bar * unit.nanometer + assert utils.is_quantity_close(state.surface_tension, 0.0 * unit.bar * unit.nanometer, rtol=0.0, atol=1e-10) + + # test initial surface tension of nonzero-gamma barostat + state = ThermodynamicState(self.membrane_barostat_alanine_gamma_nonzero, self.std_temperature) + assert utils.is_quantity_close(state.surface_tension, self.modified_surface_tension) + def test_property_volume(self): """Check that volume is computed correctly.""" # For volume-fluctuating systems volume is None. @@ -355,6 +437,9 @@ def test_property_system(self): test_cases = [(self.toluene_vacuum, TE.NO_BAROSTAT), (self.barostated_toluene, TE.BAROSTATED_NONPERIODIC), (self.multiple_barostat_alanine, TE.MULTIPLE_BAROSTATS), + (self.unsupported_anisotropic_barostat_alanine, TE.UNSUPPORTED_ANISOTROPIC_BAROSTAT), + (self.supported_anisotropic_barostat_alanine, TE.INCONSISTENT_BAROSTAT), + (self.membrane_barostat_alanine_gamma_zero, TE.INCONSISTENT_BAROSTAT), (self.inconsistent_pressure_alanine, TE.INCONSISTENT_BAROSTAT), (self.inconsistent_temperature_alanine, TE.INCONSISTENT_THERMOSTAT), (inconsistent_barostat_temperature, TE.INCONSISTENT_BAROSTAT)] @@ -422,7 +507,8 @@ def test_constructor_unsupported_barostat(self): TE = ThermodynamicsError # shortcut test_cases = [(self.barostated_toluene, TE.BAROSTATED_NONPERIODIC), (self.multiple_barostat_alanine, TE.MULTIPLE_BAROSTATS), - (self.unsupported_barostat_alanine, TE.UNSUPPORTED_BAROSTAT)] + (self.unsupported_anisotropic_barostat_alanine, TE.UNSUPPORTED_ANISOTROPIC_BAROSTAT) + ] for i, (system, err_code) in enumerate(test_cases): with nose.tools.assert_raises(TE) as cm: ThermodynamicState(system=system, temperature=self.std_temperature) @@ -584,6 +670,27 @@ def test_method_create_context(self): # Get rid of old context. This test can create a lot of them. del context, integrator + # test platform properties + state = ThermodynamicState(self.toluene_vacuum, self.std_temperature) + platform_properties = {"CpuThreads": "2"} + with nose.tools.assert_raises(ValueError) as cm: + state.create_context( + openmm.VerletIntegrator(0.001), + platform=None, + platform_properties=platform_properties + ) + assert str(cm.exception) == "To set platform_properties, you need to also specify the platform." + + platform = openmm.Platform.getPlatformByName("CPU") + context = state.create_context( + openmm.VerletIntegrator(0.001), + platform=platform, + platform_properties=platform_properties + ) + assert context.getPlatform().getPropertyValue(context, "CpuThreads") == "2" + del context + + def test_method_is_compatible(self): """ThermodynamicState context and state compatibility methods.""" @@ -620,6 +727,17 @@ def check_compatibility(state1, state2, is_compatible): barostated_alanine2.pressure = barostated_alanine.pressure + 0.2*unit.bars check_compatibility(barostated_alanine, barostated_alanine2, True) + check_compatibility( + ThermodynamicState(self.membrane_barostat_alanine_gamma_zero), + ThermodynamicState(self.membrane_barostat_alanine_gamma_nonzero), + True + ) + check_compatibility( + ThermodynamicState(self.barostated_alanine), + ThermodynamicState(self.membrane_barostat_alanine_gamma_nonzero), + False + ) + def test_method_apply_to_context(self): """ThermodynamicState.apply_to_context() method.""" friction = 5.0/unit.picosecond @@ -681,9 +799,26 @@ def test_method_apply_to_context(self): state2.apply_to_context(context) assert cm.exception.code == ThermodynamicsError.INCOMPATIBLE_ENSEMBLE + state3 = ThermodynamicState(self.membrane_barostat_alanine_gamma_zero, self.std_temperature) + with nose.tools.assert_raises(ThermodynamicsError) as cm: + state3.apply_to_context(context) + assert cm.exception.code == ThermodynamicsError.INCOMPATIBLE_ENSEMBLE + + # apply surface tension + gamma_context = openmm.Context(self.membrane_barostat_alanine_gamma_zero, openmm.VerletIntegrator(0.001)) + state3.apply_to_context(gamma_context) + assert gamma_context.getParameter(self.membrane_barostat_gamma_nonzero.SurfaceTension()) == 0.0 + state3.surface_tension = self.modified_surface_tension + state3.apply_to_context(gamma_context) + assert (gamma_context.getParameter(self.membrane_barostat_gamma_nonzero.SurfaceTension()) + == self.modified_surface_tension.value_in_unit(unit.nanometer*unit.bar)) + state3.surface_tension = 0.0 * unit.nanometer * unit.bar + + # Clean up contexts. del context, langevin_integrator del thermostated_context, verlet_integrator + del gamma_context verlet_integrator = openmm.VerletIntegrator(time_step) nvt_context = create_default_context(state2, verlet_integrator) @@ -692,6 +827,9 @@ def test_method_apply_to_context(self): assert cm.exception.code == ThermodynamicsError.INCOMPATIBLE_ENSEMBLE del nvt_context, verlet_integrator + + + def test_method_reduced_potential(self): """ThermodynamicState.reduced_potential() method.""" kj_mol = unit.kilojoule_per_mole @@ -723,6 +861,23 @@ def test_method_reduced_potential(self): state.reduced_potential(incompatible_sampler_state) assert cm.exception.code == ThermodynamicsError.INCOMPATIBLE_SAMPLER_STATE + # Compute constant surface tension reduced potential. + state = ThermodynamicState(self.membrane_barostat_alanine_gamma_nonzero, self.std_temperature) + integrator = openmm.VerletIntegrator(1.0 * unit.femtosecond) + context = create_default_context(state, integrator) + context.setPositions(self.alanine_positions) + sampler_state = SamplerState.from_context(context) + state.pressure = self.std_pressure + reduced_potential = state.reduced_potential(sampler_state) + pressure_volume_work = (self.std_pressure * sampler_state.volume * + unit.AVOGADRO_CONSTANT_NA) + surface_work = (self.modified_surface_tension * sampler_state.area_xy * + unit.AVOGADRO_CONSTANT_NA) + potential_energy = (reduced_potential / beta - pressure_volume_work + surface_work) / kj_mol + + assert np.isclose(sampler_state.potential_energy / kj_mol, potential_energy) + assert np.isclose(reduced_potential, state.reduced_potential(context)) + def test_method_reduced_potential_at_states(self): """ThermodynamicState.reduced_potential_at_states() method. @@ -762,8 +917,17 @@ def test_method_reduced_potential_at_states(self): # Compute with multi-state method. obtained_energies.extend(ThermodynamicState.reduced_potential_at_states(context, compatible_group)) + expected_energies = np.array(expected_energies) assert np.allclose(np.array(expected_energies), np.array(obtained_energies)) + # Check that the utility function does the same. + sampler_state = SamplerState(positions=self.alanine_positions) + thermodynamic_states = [thermodynamic_states[i] for i in [0, 2]] + from openmmtools.cache import ContextCache + obtained_energies = reduced_potential_at_states( + sampler_state, thermodynamic_states, ContextCache()) + assert np.allclose(expected_energies[:2], obtained_energies) + # ============================================================================= # TEST SAMPLER STATE @@ -974,6 +1138,7 @@ def test_operator_getitem(self): # The other attributes are copied correctly. assert sliced_sampler_state.volume == sampler_state.volume + assert sliced_sampler_state.area_xy == sampler_state.area_xy # Energies are undefined for as subset of atoms. assert sliced_sampler_state.kinetic_energy is None diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 000000000..71d5c913e --- /dev/null +++ b/setup.cfg @@ -0,0 +1,30 @@ +# Helper file to handle all configs + +[coverage:run] +# .coveragerc to control coverage.py and pytest-cov +omit = + # Omit the tests + */tests/* + # Omit generated versioneer + openmmtools/_version.py + +[yapf] +# YAPF, in .style.yapf files this shows up as "[style]" header +COLUMN_LIMIT = 119 +INDENT_WIDTH = 4 +USE_TABS = False + +[flake8] +# Flake8, PyFlakes, etc +max-line-length = 119 + +[versioneer] +# Automatic version numbering scheme +VCS = git +style = pep440 +versionfile_source = openmmtools/_version.py +versionfile_build = openmmtools/_version.py +tag_prefix = '' + +[aliases] +test = pytest diff --git a/setup.py b/setup.py index aa6d60ef2..f5648c8f7 100644 --- a/setup.py +++ b/setup.py @@ -1,22 +1,32 @@ """ Various Python tools for OpenMM. """ -from __future__ import print_function -import sys import distutils.extension -from setuptools import setup -import os -from os.path import relpath, join -import subprocess from Cython.Build import cythonize -DOCLINES = __doc__.split("\n") +import sys +from setuptools import setup, find_packages +import versioneer + +short_description = __doc__.split("\n") + +# from https://github.com/pytest-dev/pytest-runner#conditional-requirement +needs_pytest = {'pytest', 'test', 'ptr'}.intersection(sys.argv) +pytest_runner = ['pytest-runner'] if needs_pytest else [] + +try: + with open("README.md", "r") as handle: + long_description = handle.read() +except: + long_description = "\n".join(short_description[2:]), + +################################################################################ +# SETUP +################################################################################ + +extensions = distutils.extension.Extension("openmmtools.multistate.mixing._mix_replicas", + ['./openmmtools/multistate/mixing/_mix_replicas.pyx']) -######################## -VERSION = "0.19.0" -ISRELEASED = False -__version__ = VERSION -######################## CLASSIFIERS = """\ Development Status :: 3 - Alpha Intended Audience :: Science/Research @@ -32,151 +42,46 @@ Operating System :: MacOS """ -################################################################################ -# Writing version control information to the module -################################################################################ - -def git_version(): - # Return the git revision as a string - # copied from numpy setup.py - def _minimal_ext_cmd(cmd): - # construct minimal environment - env = {} - for k in ['SYSTEMROOT', 'PATH']: - v = os.environ.get(k) - if v is not None: - env[k] = v - # LANGUAGE is used on win32 - env['LANGUAGE'] = 'C' - env['LANG'] = 'C' - env['LC_ALL'] = 'C' - out = subprocess.Popen( - cmd, stdout=subprocess.PIPE, env=env).communicate()[0] - return out - - try: - out = _minimal_ext_cmd(['git', 'rev-parse', 'HEAD']) - GIT_REVISION = out.strip().decode('ascii') - except OSError: - GIT_REVISION = 'Unknown' - - return GIT_REVISION - - -def write_version_py(filename): - cnt = """ -# This file is automatically generated by setup.py -short_version = '%(version)s' -version = '%(version)s' -full_version = '%(full_version)s' -git_revision = '%(git_revision)s' -release = %(isrelease)s - -if not release: - version = full_version -""" - # Adding the git rev number needs to be done inside write_version_py(), - # otherwise the import of numpy.version messes up the build under Python 3. - FULLVERSION = VERSION - if os.path.exists('.git'): - GIT_REVISION = git_version() - else: - GIT_REVISION = 'Unknown' - - if not ISRELEASED: - FULLVERSION += '.dev-' + GIT_REVISION[:7] - - a = open(filename, 'w') - try: - contents = cnt % {'version': VERSION, - 'full_version': FULLVERSION, - 'git_revision': GIT_REVISION, - 'isrelease': str(ISRELEASED)} - a.write(contents) - print("Writing version.py to %s :" % os.path.abspath(filename)) - print('------------version.py-----------------') - print(contents) - print('---------------------------------------') - finally: - a.close() - -################################################################################ -# USEFUL SUBROUTINES -################################################################################ - -def find_package_data(data_root, package_root): - files = [] - for root, dirnames, filenames in os.walk(data_root): - for fn in filenames: - files.append(relpath(join(root, fn), package_root)) - return files - - -def check_dependencies(): - from distutils.version import StrictVersion - found_openmm = True - found_openmm_61_or_later = True - found_numpy = True - - try: - from simtk import openmm - openmm_version = StrictVersion(openmm.Platform.getOpenMMVersion()) - if openmm_version < StrictVersion('6.1.0'): - found_openmm_61_or_later = False - except ImportError as err: - found_openmm = False - - try: - import numpy - except: - found_numpy = False - - msg = None - bar = ('-' * 70) + "\n" + ('-' * 70) - if found_openmm: - if not found_openmm_61_or_later: - msg = [bar, '[Unmet Dependency] openmmtools requires OpenMM version 6.1 or later. You have version %s.' % openmm_version, bar] - else: - msg = [bar, '[Unmet Dependency] openmmtools requires the OpenMM python package. Refer to for details and installation instructions.', bar] - - if not found_numpy: - msg = [bar, '[Unmet Dependency] openmmtools requires the numpy python package. Refer to for numpy installation instructions.', bar] - - if msg is not None: - import textwrap - print() - print(os.linesep.join([line for e in msg for line in textwrap.wrap(e)]), file=sys.stderr) - #print('\n'.join(list(textwrap.wrap(e) for e in msg))) - -################################################################################ -# SETUP -################################################################################ - -extensions = distutils.extension.Extension("openmmtools.multistate.mixing._mix_replicas", - ['./openmmtools/multistate/mixing/_mix_replicas.pyx']) - -write_version_py('openmmtools/version.py') - setup( name='openmmtools', author='John Chodera', author_email='john.chodera@choderalab.org', - description=DOCLINES[0], - long_description="\n".join(DOCLINES[2:]), - version=__version__, + description=short_description, + long_description=long_description, + long_description_content_type="text/markdown", + version=versioneer.get_version(), + cmdclass=versioneer.get_cmdclass(), license='MIT', - url='https://github.com/choderalab/openmmtools', - platforms=['Linux', 'Mac OS-X', 'Unix', 'Windows'], + + # Which Python importable modules should be included when your package is installed + # Handled automatically by setuptools. Use 'exclude' to prevent some specific + # subpackage(s) from being added, if needed + packages=find_packages(), + + # Optional include package data to ship with your package + # Customize MANIFEST.in if the general case does not suit your needs + # Comment out this line to prevent the files from being packaged with your software + include_package_data=True, + + # Allows `setup.py test` to work correctly with pytest + setup_requires=[] + pytest_runner, + + # Additional entries you may want simply uncomment the lines you want and fill in the data + url='https://github.com/choderalab/openmmtools', # Website + # install_requires=[], # Required packages, pulls from pip if needed; do not use for Conda deployment + platforms=['Linux', + 'Mac OS-X', + 'Unix', + 'Windows'], # Valid platforms your code works on, adjust to your flavor classifiers=CLASSIFIERS.splitlines(), - packages=['openmmtools', 'openmmtools.tests', 'openmmtools.scripts', 'openmmtools.storage','openmmtools.multistate', 'openmmtools.multistate.mixing'], - package_dir={'openmmtools': 'openmmtools'}, - package_data={'openmmtools': find_package_data('openmmtools/data', 'openmmtools')}, + python_requires=">=3.6", # Python version restrictions + + # Manual control if final package is compressible or not, set False to prevent the .egg from being made zip_safe=False, - scripts=[], + ext_modules=cythonize(extensions), entry_points={'console_scripts': [ 'test-openmm-platforms = openmmtools.scripts.test_openmm_platforms:main', 'benchmark-alchemy = openmmtools.tests.test_alchemy:benchmark_alchemy_from_pdb', ]}, ) -check_dependencies() diff --git a/versioneer.py b/versioneer.py new file mode 100644 index 000000000..64fea1c89 --- /dev/null +++ b/versioneer.py @@ -0,0 +1,1822 @@ + +# Version: 0.18 + +"""The Versioneer - like a rocketeer, but for versions. + +The Versioneer +============== + +* like a rocketeer, but for versions! +* https://github.com/warner/python-versioneer +* Brian Warner +* License: Public Domain +* Compatible With: python2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6, and pypy +* [![Latest Version] +(https://pypip.in/version/versioneer/badge.svg?style=flat) +](https://pypi.python.org/pypi/versioneer/) +* [![Build Status] +(https://travis-ci.org/warner/python-versioneer.png?branch=master) +](https://travis-ci.org/warner/python-versioneer) + +This is a tool for managing a recorded version number in distutils-based +python projects. The goal is to remove the tedious and error-prone "update +the embedded version string" step from your release process. Making a new +release should be as easy as recording a new tag in your version-control +system, and maybe making new tarballs. + + +## Quick Install + +* `pip install versioneer` to somewhere to your $PATH +* add a `[versioneer]` section to your setup.cfg (see below) +* run `versioneer install` in your source tree, commit the results + +## Version Identifiers + +Source trees come from a variety of places: + +* a version-control system checkout (mostly used by developers) +* a nightly tarball, produced by build automation +* a snapshot tarball, produced by a web-based VCS browser, like github's + "tarball from tag" feature +* a release tarball, produced by "setup.py sdist", distributed through PyPI + +Within each source tree, the version identifier (either a string or a number, +this tool is format-agnostic) can come from a variety of places: + +* ask the VCS tool itself, e.g. "git describe" (for checkouts), which knows + about recent "tags" and an absolute revision-id +* the name of the directory into which the tarball was unpacked +* an expanded VCS keyword ($Id$, etc) +* a `_version.py` created by some earlier build step + +For released software, the version identifier is closely related to a VCS +tag. Some projects use tag names that include more than just the version +string (e.g. "myproject-1.2" instead of just "1.2"), in which case the tool +needs to strip the tag prefix to extract the version identifier. For +unreleased software (between tags), the version identifier should provide +enough information to help developers recreate the same tree, while also +giving them an idea of roughly how old the tree is (after version 1.2, before +version 1.3). Many VCS systems can report a description that captures this, +for example `git describe --tags --dirty --always` reports things like +"0.7-1-g574ab98-dirty" to indicate that the checkout is one revision past the +0.7 tag, has a unique revision id of "574ab98", and is "dirty" (it has +uncommitted changes. + +The version identifier is used for multiple purposes: + +* to allow the module to self-identify its version: `myproject.__version__` +* to choose a name and prefix for a 'setup.py sdist' tarball + +## Theory of Operation + +Versioneer works by adding a special `_version.py` file into your source +tree, where your `__init__.py` can import it. This `_version.py` knows how to +dynamically ask the VCS tool for version information at import time. + +`_version.py` also contains `$Revision$` markers, and the installation +process marks `_version.py` to have this marker rewritten with a tag name +during the `git archive` command. As a result, generated tarballs will +contain enough information to get the proper version. + +To allow `setup.py` to compute a version too, a `versioneer.py` is added to +the top level of your source tree, next to `setup.py` and the `setup.cfg` +that configures it. This overrides several distutils/setuptools commands to +compute the version when invoked, and changes `setup.py build` and `setup.py +sdist` to replace `_version.py` with a small static file that contains just +the generated version data. + +## Installation + +See [INSTALL.md](./INSTALL.md) for detailed installation instructions. + +## Version-String Flavors + +Code which uses Versioneer can learn about its version string at runtime by +importing `_version` from your main `__init__.py` file and running the +`get_versions()` function. From the "outside" (e.g. in `setup.py`), you can +import the top-level `versioneer.py` and run `get_versions()`. + +Both functions return a dictionary with different flavors of version +information: + +* `['version']`: A condensed version string, rendered using the selected + style. This is the most commonly used value for the project's version + string. The default "pep440" style yields strings like `0.11`, + `0.11+2.g1076c97`, or `0.11+2.g1076c97.dirty`. See the "Styles" section + below for alternative styles. + +* `['full-revisionid']`: detailed revision identifier. For Git, this is the + full SHA1 commit id, e.g. "1076c978a8d3cfc70f408fe5974aa6c092c949ac". + +* `['date']`: Date and time of the latest `HEAD` commit. For Git, it is the + commit date in ISO 8601 format. This will be None if the date is not + available. + +* `['dirty']`: a boolean, True if the tree has uncommitted changes. Note that + this is only accurate if run in a VCS checkout, otherwise it is likely to + be False or None + +* `['error']`: if the version string could not be computed, this will be set + to a string describing the problem, otherwise it will be None. It may be + useful to throw an exception in setup.py if this is set, to avoid e.g. + creating tarballs with a version string of "unknown". + +Some variants are more useful than others. Including `full-revisionid` in a +bug report should allow developers to reconstruct the exact code being tested +(or indicate the presence of local changes that should be shared with the +developers). `version` is suitable for display in an "about" box or a CLI +`--version` output: it can be easily compared against release notes and lists +of bugs fixed in various releases. + +The installer adds the following text to your `__init__.py` to place a basic +version in `YOURPROJECT.__version__`: + + from ._version import get_versions + __version__ = get_versions()['version'] + del get_versions + +## Styles + +The setup.cfg `style=` configuration controls how the VCS information is +rendered into a version string. + +The default style, "pep440", produces a PEP440-compliant string, equal to the +un-prefixed tag name for actual releases, and containing an additional "local +version" section with more detail for in-between builds. For Git, this is +TAG[+DISTANCE.gHEX[.dirty]] , using information from `git describe --tags +--dirty --always`. For example "0.11+2.g1076c97.dirty" indicates that the +tree is like the "1076c97" commit but has uncommitted changes (".dirty"), and +that this commit is two revisions ("+2") beyond the "0.11" tag. For released +software (exactly equal to a known tag), the identifier will only contain the +stripped tag, e.g. "0.11". + +Other styles are available. See [details.md](details.md) in the Versioneer +source tree for descriptions. + +## Debugging + +Versioneer tries to avoid fatal errors: if something goes wrong, it will tend +to return a version of "0+unknown". To investigate the problem, run `setup.py +version`, which will run the version-lookup code in a verbose mode, and will +display the full contents of `get_versions()` (including the `error` string, +which may help identify what went wrong). + +## Known Limitations + +Some situations are known to cause problems for Versioneer. This details the +most significant ones. More can be found on Github +[issues page](https://github.com/warner/python-versioneer/issues). + +### Subprojects + +Versioneer has limited support for source trees in which `setup.py` is not in +the root directory (e.g. `setup.py` and `.git/` are *not* siblings). The are +two common reasons why `setup.py` might not be in the root: + +* Source trees which contain multiple subprojects, such as + [Buildbot](https://github.com/buildbot/buildbot), which contains both + "master" and "slave" subprojects, each with their own `setup.py`, + `setup.cfg`, and `tox.ini`. Projects like these produce multiple PyPI + distributions (and upload multiple independently-installable tarballs). +* Source trees whose main purpose is to contain a C library, but which also + provide bindings to Python (and perhaps other langauges) in subdirectories. + +Versioneer will look for `.git` in parent directories, and most operations +should get the right version string. However `pip` and `setuptools` have bugs +and implementation details which frequently cause `pip install .` from a +subproject directory to fail to find a correct version string (so it usually +defaults to `0+unknown`). + +`pip install --editable .` should work correctly. `setup.py install` might +work too. + +Pip-8.1.1 is known to have this problem, but hopefully it will get fixed in +some later version. + +[Bug #38](https://github.com/warner/python-versioneer/issues/38) is tracking +this issue. The discussion in +[PR #61](https://github.com/warner/python-versioneer/pull/61) describes the +issue from the Versioneer side in more detail. +[pip PR#3176](https://github.com/pypa/pip/pull/3176) and +[pip PR#3615](https://github.com/pypa/pip/pull/3615) contain work to improve +pip to let Versioneer work correctly. + +Versioneer-0.16 and earlier only looked for a `.git` directory next to the +`setup.cfg`, so subprojects were completely unsupported with those releases. + +### Editable installs with setuptools <= 18.5 + +`setup.py develop` and `pip install --editable .` allow you to install a +project into a virtualenv once, then continue editing the source code (and +test) without re-installing after every change. + +"Entry-point scripts" (`setup(entry_points={"console_scripts": ..})`) are a +convenient way to specify executable scripts that should be installed along +with the python package. + +These both work as expected when using modern setuptools. When using +setuptools-18.5 or earlier, however, certain operations will cause +`pkg_resources.DistributionNotFound` errors when running the entrypoint +script, which must be resolved by re-installing the package. This happens +when the install happens with one version, then the egg_info data is +regenerated while a different version is checked out. Many setup.py commands +cause egg_info to be rebuilt (including `sdist`, `wheel`, and installing into +a different virtualenv), so this can be surprising. + +[Bug #83](https://github.com/warner/python-versioneer/issues/83) describes +this one, but upgrading to a newer version of setuptools should probably +resolve it. + +### Unicode version strings + +While Versioneer works (and is continually tested) with both Python 2 and +Python 3, it is not entirely consistent with bytes-vs-unicode distinctions. +Newer releases probably generate unicode version strings on py2. It's not +clear that this is wrong, but it may be surprising for applications when then +write these strings to a network connection or include them in bytes-oriented +APIs like cryptographic checksums. + +[Bug #71](https://github.com/warner/python-versioneer/issues/71) investigates +this question. + + +## Updating Versioneer + +To upgrade your project to a new release of Versioneer, do the following: + +* install the new Versioneer (`pip install -U versioneer` or equivalent) +* edit `setup.cfg`, if necessary, to include any new configuration settings + indicated by the release notes. See [UPGRADING](./UPGRADING.md) for details. +* re-run `versioneer install` in your source tree, to replace + `SRC/_version.py` +* commit any changed files + +## Future Directions + +This tool is designed to make it easily extended to other version-control +systems: all VCS-specific components are in separate directories like +src/git/ . The top-level `versioneer.py` script is assembled from these +components by running make-versioneer.py . In the future, make-versioneer.py +will take a VCS name as an argument, and will construct a version of +`versioneer.py` that is specific to the given VCS. It might also take the +configuration arguments that are currently provided manually during +installation by editing setup.py . Alternatively, it might go the other +direction and include code from all supported VCS systems, reducing the +number of intermediate scripts. + + +## License + +To make Versioneer easier to embed, all its code is dedicated to the public +domain. The `_version.py` that it creates is also in the public domain. +Specifically, both are released under the Creative Commons "Public Domain +Dedication" license (CC0-1.0), as described in +https://creativecommons.org/publicdomain/zero/1.0/ . + +""" + +from __future__ import print_function +try: + import configparser +except ImportError: + import ConfigParser as configparser +import errno +import json +import os +import re +import subprocess +import sys + + +class VersioneerConfig: + """Container for Versioneer configuration parameters.""" + + +def get_root(): + """Get the project root directory. + + We require that all commands are run from the project root, i.e. the + directory that contains setup.py, setup.cfg, and versioneer.py . + """ + root = os.path.realpath(os.path.abspath(os.getcwd())) + setup_py = os.path.join(root, "setup.py") + versioneer_py = os.path.join(root, "versioneer.py") + if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)): + # allow 'python path/to/setup.py COMMAND' + root = os.path.dirname(os.path.realpath(os.path.abspath(sys.argv[0]))) + setup_py = os.path.join(root, "setup.py") + versioneer_py = os.path.join(root, "versioneer.py") + if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)): + err = ("Versioneer was unable to run the project root directory. " + "Versioneer requires setup.py to be executed from " + "its immediate directory (like 'python setup.py COMMAND'), " + "or in a way that lets it use sys.argv[0] to find the root " + "(like 'python path/to/setup.py COMMAND').") + raise VersioneerBadRootError(err) + try: + # Certain runtime workflows (setup.py install/develop in a setuptools + # tree) execute all dependencies in a single python process, so + # "versioneer" may be imported multiple times, and python's shared + # module-import table will cache the first one. So we can't use + # os.path.dirname(__file__), as that will find whichever + # versioneer.py was first imported, even in later projects. + me = os.path.realpath(os.path.abspath(__file__)) + me_dir = os.path.normcase(os.path.splitext(me)[0]) + vsr_dir = os.path.normcase(os.path.splitext(versioneer_py)[0]) + if me_dir != vsr_dir: + print("Warning: build in %s is using versioneer.py from %s" + % (os.path.dirname(me), versioneer_py)) + except NameError: + pass + return root + + +def get_config_from_root(root): + """Read the project setup.cfg file to determine Versioneer config.""" + # This might raise EnvironmentError (if setup.cfg is missing), or + # configparser.NoSectionError (if it lacks a [versioneer] section), or + # configparser.NoOptionError (if it lacks "VCS="). See the docstring at + # the top of versioneer.py for instructions on writing your setup.cfg . + setup_cfg = os.path.join(root, "setup.cfg") + parser = configparser.SafeConfigParser() + with open(setup_cfg, "r") as f: + parser.readfp(f) + VCS = parser.get("versioneer", "VCS") # mandatory + + def get(parser, name): + if parser.has_option("versioneer", name): + return parser.get("versioneer", name) + return None + cfg = VersioneerConfig() + cfg.VCS = VCS + cfg.style = get(parser, "style") or "" + cfg.versionfile_source = get(parser, "versionfile_source") + cfg.versionfile_build = get(parser, "versionfile_build") + cfg.tag_prefix = get(parser, "tag_prefix") + if cfg.tag_prefix in ("''", '""'): + cfg.tag_prefix = "" + cfg.parentdir_prefix = get(parser, "parentdir_prefix") + cfg.verbose = get(parser, "verbose") + return cfg + + +class NotThisMethod(Exception): + """Exception raised if a method is not valid for the current scenario.""" + + +# these dictionaries contain VCS-specific tools +LONG_VERSION_PY = {} +HANDLERS = {} + + +def register_vcs_handler(vcs, method): # decorator + """Decorator to mark a method as the handler for a particular VCS.""" + def decorate(f): + """Store f in HANDLERS[vcs][method].""" + if vcs not in HANDLERS: + HANDLERS[vcs] = {} + HANDLERS[vcs][method] = f + return f + return decorate + + +def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, + env=None): + """Call the given command(s).""" + assert isinstance(commands, list) + p = None + for c in commands: + try: + dispcmd = str([c] + args) + # remember shell=False, so use git.cmd on windows, not just git + p = subprocess.Popen([c] + args, cwd=cwd, env=env, + stdout=subprocess.PIPE, + stderr=(subprocess.PIPE if hide_stderr + else None)) + break + except EnvironmentError: + e = sys.exc_info()[1] + if e.errno == errno.ENOENT: + continue + if verbose: + print("unable to run %s" % dispcmd) + print(e) + return None, None + else: + if verbose: + print("unable to find command, tried %s" % (commands,)) + return None, None + stdout = p.communicate()[0].strip() + if sys.version_info[0] >= 3: + stdout = stdout.decode() + if p.returncode != 0: + if verbose: + print("unable to run %s (error)" % dispcmd) + print("stdout was %s" % stdout) + return None, p.returncode + return stdout, p.returncode + + +LONG_VERSION_PY['git'] = ''' +# This file helps to compute a version number in source trees obtained from +# git-archive tarball (such as those provided by githubs download-from-tag +# feature). Distribution tarballs (built by setup.py sdist) and build +# directories (produced by setup.py build) will contain a much shorter file +# that just contains the computed version number. + +# This file is released into the public domain. Generated by +# versioneer-0.18 (https://github.com/warner/python-versioneer) + +"""Git implementation of _version.py.""" + +import errno +import os +import re +import subprocess +import sys + + +def get_keywords(): + """Get the keywords needed to look up the version information.""" + # these strings will be replaced by git during git-archive. + # setup.py/versioneer.py will grep for the variable names, so they must + # each be defined on a line of their own. _version.py will just call + # get_keywords(). + git_refnames = "%(DOLLAR)sFormat:%%d%(DOLLAR)s" + git_full = "%(DOLLAR)sFormat:%%H%(DOLLAR)s" + git_date = "%(DOLLAR)sFormat:%%ci%(DOLLAR)s" + keywords = {"refnames": git_refnames, "full": git_full, "date": git_date} + return keywords + + +class VersioneerConfig: + """Container for Versioneer configuration parameters.""" + + +def get_config(): + """Create, populate and return the VersioneerConfig() object.""" + # these strings are filled in when 'setup.py versioneer' creates + # _version.py + cfg = VersioneerConfig() + cfg.VCS = "git" + cfg.style = "%(STYLE)s" + cfg.tag_prefix = "%(TAG_PREFIX)s" + cfg.parentdir_prefix = "%(PARENTDIR_PREFIX)s" + cfg.versionfile_source = "%(VERSIONFILE_SOURCE)s" + cfg.verbose = False + return cfg + + +class NotThisMethod(Exception): + """Exception raised if a method is not valid for the current scenario.""" + + +LONG_VERSION_PY = {} +HANDLERS = {} + + +def register_vcs_handler(vcs, method): # decorator + """Decorator to mark a method as the handler for a particular VCS.""" + def decorate(f): + """Store f in HANDLERS[vcs][method].""" + if vcs not in HANDLERS: + HANDLERS[vcs] = {} + HANDLERS[vcs][method] = f + return f + return decorate + + +def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, + env=None): + """Call the given command(s).""" + assert isinstance(commands, list) + p = None + for c in commands: + try: + dispcmd = str([c] + args) + # remember shell=False, so use git.cmd on windows, not just git + p = subprocess.Popen([c] + args, cwd=cwd, env=env, + stdout=subprocess.PIPE, + stderr=(subprocess.PIPE if hide_stderr + else None)) + break + except EnvironmentError: + e = sys.exc_info()[1] + if e.errno == errno.ENOENT: + continue + if verbose: + print("unable to run %%s" %% dispcmd) + print(e) + return None, None + else: + if verbose: + print("unable to find command, tried %%s" %% (commands,)) + return None, None + stdout = p.communicate()[0].strip() + if sys.version_info[0] >= 3: + stdout = stdout.decode() + if p.returncode != 0: + if verbose: + print("unable to run %%s (error)" %% dispcmd) + print("stdout was %%s" %% stdout) + return None, p.returncode + return stdout, p.returncode + + +def versions_from_parentdir(parentdir_prefix, root, verbose): + """Try to determine the version from the parent directory name. + + Source tarballs conventionally unpack into a directory that includes both + the project name and a version string. We will also support searching up + two directory levels for an appropriately named parent directory + """ + rootdirs = [] + + for i in range(3): + dirname = os.path.basename(root) + if dirname.startswith(parentdir_prefix): + return {"version": dirname[len(parentdir_prefix):], + "full-revisionid": None, + "dirty": False, "error": None, "date": None} + else: + rootdirs.append(root) + root = os.path.dirname(root) # up a level + + if verbose: + print("Tried directories %%s but none started with prefix %%s" %% + (str(rootdirs), parentdir_prefix)) + raise NotThisMethod("rootdir doesn't start with parentdir_prefix") + + +@register_vcs_handler("git", "get_keywords") +def git_get_keywords(versionfile_abs): + """Extract version information from the given file.""" + # the code embedded in _version.py can just fetch the value of these + # keywords. When used from setup.py, we don't want to import _version.py, + # so we do it with a regexp instead. This function is not used from + # _version.py. + keywords = {} + try: + f = open(versionfile_abs, "r") + for line in f.readlines(): + if line.strip().startswith("git_refnames ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["refnames"] = mo.group(1) + if line.strip().startswith("git_full ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["full"] = mo.group(1) + if line.strip().startswith("git_date ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["date"] = mo.group(1) + f.close() + except EnvironmentError: + pass + return keywords + + +@register_vcs_handler("git", "keywords") +def git_versions_from_keywords(keywords, tag_prefix, verbose): + """Get version information from git keywords.""" + if not keywords: + raise NotThisMethod("no keywords at all, weird") + date = keywords.get("date") + if date is not None: + # git-2.2.0 added "%%cI", which expands to an ISO-8601 -compliant + # datestamp. However we prefer "%%ci" (which expands to an "ISO-8601 + # -like" string, which we must then edit to make compliant), because + # it's been around since git-1.5.3, and it's too difficult to + # discover which version we're using, or to work around using an + # older one. + date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) + refnames = keywords["refnames"].strip() + if refnames.startswith("$Format"): + if verbose: + print("keywords are unexpanded, not using") + raise NotThisMethod("unexpanded keywords, not a git-archive tarball") + refs = set([r.strip() for r in refnames.strip("()").split(",")]) + # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of + # just "foo-1.0". If we see a "tag: " prefix, prefer those. + TAG = "tag: " + tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) + if not tags: + # Either we're using git < 1.8.3, or there really are no tags. We use + # a heuristic: assume all version tags have a digit. The old git %%d + # expansion behaves like git log --decorate=short and strips out the + # refs/heads/ and refs/tags/ prefixes that would let us distinguish + # between branches and tags. By ignoring refnames without digits, we + # filter out many common branch names like "release" and + # "stabilization", as well as "HEAD" and "master". + tags = set([r for r in refs if re.search(r'\d', r)]) + if verbose: + print("discarding '%%s', no digits" %% ",".join(refs - tags)) + if verbose: + print("likely tags: %%s" %% ",".join(sorted(tags))) + for ref in sorted(tags): + # sorting will prefer e.g. "2.0" over "2.0rc1" + if ref.startswith(tag_prefix): + r = ref[len(tag_prefix):] + if verbose: + print("picking %%s" %% r) + return {"version": r, + "full-revisionid": keywords["full"].strip(), + "dirty": False, "error": None, + "date": date} + # no suitable tags, so version is "0+unknown", but full hex is still there + if verbose: + print("no suitable tags, using unknown + full revision id") + return {"version": "0+unknown", + "full-revisionid": keywords["full"].strip(), + "dirty": False, "error": "no suitable tags", "date": None} + + +@register_vcs_handler("git", "pieces_from_vcs") +def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): + """Get version from 'git describe' in the root of the source tree. + + This only gets called if the git-archive 'subst' keywords were *not* + expanded, and _version.py hasn't already been rewritten with a short + version string, meaning we're inside a checked out source tree. + """ + GITS = ["git"] + if sys.platform == "win32": + GITS = ["git.cmd", "git.exe"] + + out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, + hide_stderr=True) + if rc != 0: + if verbose: + print("Directory %%s not under git control" %% root) + raise NotThisMethod("'git rev-parse --git-dir' returned error") + + # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] + # if there isn't one, this yields HEX[-dirty] (no NUM) + describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", + "--always", "--long", + "--match", "%%s*" %% tag_prefix], + cwd=root) + # --long was added in git-1.5.5 + if describe_out is None: + raise NotThisMethod("'git describe' failed") + describe_out = describe_out.strip() + full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) + if full_out is None: + raise NotThisMethod("'git rev-parse' failed") + full_out = full_out.strip() + + pieces = {} + pieces["long"] = full_out + pieces["short"] = full_out[:7] # maybe improved later + pieces["error"] = None + + # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] + # TAG might have hyphens. + git_describe = describe_out + + # look for -dirty suffix + dirty = git_describe.endswith("-dirty") + pieces["dirty"] = dirty + if dirty: + git_describe = git_describe[:git_describe.rindex("-dirty")] + + # now we have TAG-NUM-gHEX or HEX + + if "-" in git_describe: + # TAG-NUM-gHEX + mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) + if not mo: + # unparseable. Maybe git-describe is misbehaving? + pieces["error"] = ("unable to parse git-describe output: '%%s'" + %% describe_out) + return pieces + + # tag + full_tag = mo.group(1) + if not full_tag.startswith(tag_prefix): + if verbose: + fmt = "tag '%%s' doesn't start with prefix '%%s'" + print(fmt %% (full_tag, tag_prefix)) + pieces["error"] = ("tag '%%s' doesn't start with prefix '%%s'" + %% (full_tag, tag_prefix)) + return pieces + pieces["closest-tag"] = full_tag[len(tag_prefix):] + + # distance: number of commits since tag + pieces["distance"] = int(mo.group(2)) + + # commit: short hex revision ID + pieces["short"] = mo.group(3) + + else: + # HEX: no tags + pieces["closest-tag"] = None + count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], + cwd=root) + pieces["distance"] = int(count_out) # total number of commits + + # commit date: see ISO-8601 comment in git_versions_from_keywords() + date = run_command(GITS, ["show", "-s", "--format=%%ci", "HEAD"], + cwd=root)[0].strip() + pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) + + return pieces + + +def plus_or_dot(pieces): + """Return a + if we don't already have one, else return a .""" + if "+" in pieces.get("closest-tag", ""): + return "." + return "+" + + +def render_pep440(pieces): + """Build up version string, with post-release "local version identifier". + + Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you + get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty + + Exceptions: + 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += plus_or_dot(pieces) + rendered += "%%d.g%%s" %% (pieces["distance"], pieces["short"]) + if pieces["dirty"]: + rendered += ".dirty" + else: + # exception #1 + rendered = "0+untagged.%%d.g%%s" %% (pieces["distance"], + pieces["short"]) + if pieces["dirty"]: + rendered += ".dirty" + return rendered + + +def render_pep440_pre(pieces): + """TAG[.post.devDISTANCE] -- No -dirty. + + Exceptions: + 1: no tags. 0.post.devDISTANCE + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"]: + rendered += ".post.dev%%d" %% pieces["distance"] + else: + # exception #1 + rendered = "0.post.dev%%d" %% pieces["distance"] + return rendered + + +def render_pep440_post(pieces): + """TAG[.postDISTANCE[.dev0]+gHEX] . + + The ".dev0" means dirty. Note that .dev0 sorts backwards + (a dirty tree will appear "older" than the corresponding clean one), + but you shouldn't be releasing software with -dirty anyways. + + Exceptions: + 1: no tags. 0.postDISTANCE[.dev0] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += ".post%%d" %% pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + rendered += plus_or_dot(pieces) + rendered += "g%%s" %% pieces["short"] + else: + # exception #1 + rendered = "0.post%%d" %% pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + rendered += "+g%%s" %% pieces["short"] + return rendered + + +def render_pep440_old(pieces): + """TAG[.postDISTANCE[.dev0]] . + + The ".dev0" means dirty. + + Eexceptions: + 1: no tags. 0.postDISTANCE[.dev0] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += ".post%%d" %% pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + else: + # exception #1 + rendered = "0.post%%d" %% pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + return rendered + + +def render_git_describe(pieces): + """TAG[-DISTANCE-gHEX][-dirty]. + + Like 'git describe --tags --dirty --always'. + + Exceptions: + 1: no tags. HEX[-dirty] (note: no 'g' prefix) + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"]: + rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"]) + else: + # exception #1 + rendered = pieces["short"] + if pieces["dirty"]: + rendered += "-dirty" + return rendered + + +def render_git_describe_long(pieces): + """TAG-DISTANCE-gHEX[-dirty]. + + Like 'git describe --tags --dirty --always -long'. + The distance/hash is unconditional. + + Exceptions: + 1: no tags. HEX[-dirty] (note: no 'g' prefix) + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"]) + else: + # exception #1 + rendered = pieces["short"] + if pieces["dirty"]: + rendered += "-dirty" + return rendered + + +def render(pieces, style): + """Render the given version pieces into the requested style.""" + if pieces["error"]: + return {"version": "unknown", + "full-revisionid": pieces.get("long"), + "dirty": None, + "error": pieces["error"], + "date": None} + + if not style or style == "default": + style = "pep440" # the default + + if style == "pep440": + rendered = render_pep440(pieces) + elif style == "pep440-pre": + rendered = render_pep440_pre(pieces) + elif style == "pep440-post": + rendered = render_pep440_post(pieces) + elif style == "pep440-old": + rendered = render_pep440_old(pieces) + elif style == "git-describe": + rendered = render_git_describe(pieces) + elif style == "git-describe-long": + rendered = render_git_describe_long(pieces) + else: + raise ValueError("unknown style '%%s'" %% style) + + return {"version": rendered, "full-revisionid": pieces["long"], + "dirty": pieces["dirty"], "error": None, + "date": pieces.get("date")} + + +def get_versions(): + """Get version information or return default if unable to do so.""" + # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have + # __file__, we can work backwards from there to the root. Some + # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which + # case we can only use expanded keywords. + + cfg = get_config() + verbose = cfg.verbose + + try: + return git_versions_from_keywords(get_keywords(), cfg.tag_prefix, + verbose) + except NotThisMethod: + pass + + try: + root = os.path.realpath(__file__) + # versionfile_source is the relative path from the top of the source + # tree (where the .git directory might live) to this file. Invert + # this to find the root from __file__. + for i in cfg.versionfile_source.split('/'): + root = os.path.dirname(root) + except NameError: + return {"version": "0+unknown", "full-revisionid": None, + "dirty": None, + "error": "unable to find root of source tree", + "date": None} + + try: + pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose) + return render(pieces, cfg.style) + except NotThisMethod: + pass + + try: + if cfg.parentdir_prefix: + return versions_from_parentdir(cfg.parentdir_prefix, root, verbose) + except NotThisMethod: + pass + + return {"version": "0+unknown", "full-revisionid": None, + "dirty": None, + "error": "unable to compute version", "date": None} +''' + + +@register_vcs_handler("git", "get_keywords") +def git_get_keywords(versionfile_abs): + """Extract version information from the given file.""" + # the code embedded in _version.py can just fetch the value of these + # keywords. When used from setup.py, we don't want to import _version.py, + # so we do it with a regexp instead. This function is not used from + # _version.py. + keywords = {} + try: + f = open(versionfile_abs, "r") + for line in f.readlines(): + if line.strip().startswith("git_refnames ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["refnames"] = mo.group(1) + if line.strip().startswith("git_full ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["full"] = mo.group(1) + if line.strip().startswith("git_date ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["date"] = mo.group(1) + f.close() + except EnvironmentError: + pass + return keywords + + +@register_vcs_handler("git", "keywords") +def git_versions_from_keywords(keywords, tag_prefix, verbose): + """Get version information from git keywords.""" + if not keywords: + raise NotThisMethod("no keywords at all, weird") + date = keywords.get("date") + if date is not None: + # git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant + # datestamp. However we prefer "%ci" (which expands to an "ISO-8601 + # -like" string, which we must then edit to make compliant), because + # it's been around since git-1.5.3, and it's too difficult to + # discover which version we're using, or to work around using an + # older one. + date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) + refnames = keywords["refnames"].strip() + if refnames.startswith("$Format"): + if verbose: + print("keywords are unexpanded, not using") + raise NotThisMethod("unexpanded keywords, not a git-archive tarball") + refs = set([r.strip() for r in refnames.strip("()").split(",")]) + # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of + # just "foo-1.0". If we see a "tag: " prefix, prefer those. + TAG = "tag: " + tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) + if not tags: + # Either we're using git < 1.8.3, or there really are no tags. We use + # a heuristic: assume all version tags have a digit. The old git %d + # expansion behaves like git log --decorate=short and strips out the + # refs/heads/ and refs/tags/ prefixes that would let us distinguish + # between branches and tags. By ignoring refnames without digits, we + # filter out many common branch names like "release" and + # "stabilization", as well as "HEAD" and "master". + tags = set([r for r in refs if re.search(r'\d', r)]) + if verbose: + print("discarding '%s', no digits" % ",".join(refs - tags)) + if verbose: + print("likely tags: %s" % ",".join(sorted(tags))) + for ref in sorted(tags): + # sorting will prefer e.g. "2.0" over "2.0rc1" + if ref.startswith(tag_prefix): + r = ref[len(tag_prefix):] + if verbose: + print("picking %s" % r) + return {"version": r, + "full-revisionid": keywords["full"].strip(), + "dirty": False, "error": None, + "date": date} + # no suitable tags, so version is "0+unknown", but full hex is still there + if verbose: + print("no suitable tags, using unknown + full revision id") + return {"version": "0+unknown", + "full-revisionid": keywords["full"].strip(), + "dirty": False, "error": "no suitable tags", "date": None} + + +@register_vcs_handler("git", "pieces_from_vcs") +def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): + """Get version from 'git describe' in the root of the source tree. + + This only gets called if the git-archive 'subst' keywords were *not* + expanded, and _version.py hasn't already been rewritten with a short + version string, meaning we're inside a checked out source tree. + """ + GITS = ["git"] + if sys.platform == "win32": + GITS = ["git.cmd", "git.exe"] + + out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, + hide_stderr=True) + if rc != 0: + if verbose: + print("Directory %s not under git control" % root) + raise NotThisMethod("'git rev-parse --git-dir' returned error") + + # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] + # if there isn't one, this yields HEX[-dirty] (no NUM) + describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", + "--always", "--long", + "--match", "%s*" % tag_prefix], + cwd=root) + # --long was added in git-1.5.5 + if describe_out is None: + raise NotThisMethod("'git describe' failed") + describe_out = describe_out.strip() + full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) + if full_out is None: + raise NotThisMethod("'git rev-parse' failed") + full_out = full_out.strip() + + pieces = {} + pieces["long"] = full_out + pieces["short"] = full_out[:7] # maybe improved later + pieces["error"] = None + + # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] + # TAG might have hyphens. + git_describe = describe_out + + # look for -dirty suffix + dirty = git_describe.endswith("-dirty") + pieces["dirty"] = dirty + if dirty: + git_describe = git_describe[:git_describe.rindex("-dirty")] + + # now we have TAG-NUM-gHEX or HEX + + if "-" in git_describe: + # TAG-NUM-gHEX + mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) + if not mo: + # unparseable. Maybe git-describe is misbehaving? + pieces["error"] = ("unable to parse git-describe output: '%s'" + % describe_out) + return pieces + + # tag + full_tag = mo.group(1) + if not full_tag.startswith(tag_prefix): + if verbose: + fmt = "tag '%s' doesn't start with prefix '%s'" + print(fmt % (full_tag, tag_prefix)) + pieces["error"] = ("tag '%s' doesn't start with prefix '%s'" + % (full_tag, tag_prefix)) + return pieces + pieces["closest-tag"] = full_tag[len(tag_prefix):] + + # distance: number of commits since tag + pieces["distance"] = int(mo.group(2)) + + # commit: short hex revision ID + pieces["short"] = mo.group(3) + + else: + # HEX: no tags + pieces["closest-tag"] = None + count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], + cwd=root) + pieces["distance"] = int(count_out) # total number of commits + + # commit date: see ISO-8601 comment in git_versions_from_keywords() + date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], + cwd=root)[0].strip() + pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) + + return pieces + + +def do_vcs_install(manifest_in, versionfile_source, ipy): + """Git-specific installation logic for Versioneer. + + For Git, this means creating/changing .gitattributes to mark _version.py + for export-subst keyword substitution. + """ + GITS = ["git"] + if sys.platform == "win32": + GITS = ["git.cmd", "git.exe"] + files = [manifest_in, versionfile_source] + if ipy: + files.append(ipy) + try: + me = __file__ + if me.endswith(".pyc") or me.endswith(".pyo"): + me = os.path.splitext(me)[0] + ".py" + versioneer_file = os.path.relpath(me) + except NameError: + versioneer_file = "versioneer.py" + files.append(versioneer_file) + present = False + try: + f = open(".gitattributes", "r") + for line in f.readlines(): + if line.strip().startswith(versionfile_source): + if "export-subst" in line.strip().split()[1:]: + present = True + f.close() + except EnvironmentError: + pass + if not present: + f = open(".gitattributes", "a+") + f.write("%s export-subst\n" % versionfile_source) + f.close() + files.append(".gitattributes") + run_command(GITS, ["add", "--"] + files) + + +def versions_from_parentdir(parentdir_prefix, root, verbose): + """Try to determine the version from the parent directory name. + + Source tarballs conventionally unpack into a directory that includes both + the project name and a version string. We will also support searching up + two directory levels for an appropriately named parent directory + """ + rootdirs = [] + + for i in range(3): + dirname = os.path.basename(root) + if dirname.startswith(parentdir_prefix): + return {"version": dirname[len(parentdir_prefix):], + "full-revisionid": None, + "dirty": False, "error": None, "date": None} + else: + rootdirs.append(root) + root = os.path.dirname(root) # up a level + + if verbose: + print("Tried directories %s but none started with prefix %s" % + (str(rootdirs), parentdir_prefix)) + raise NotThisMethod("rootdir doesn't start with parentdir_prefix") + + +SHORT_VERSION_PY = """ +# This file was generated by 'versioneer.py' (0.18) from +# revision-control system data, or from the parent directory name of an +# unpacked source archive. Distribution tarballs contain a pre-generated copy +# of this file. + +import json + +version_json = ''' +%s +''' # END VERSION_JSON + + +def get_versions(): + return json.loads(version_json) +""" + + +def versions_from_file(filename): + """Try to determine the version from _version.py if present.""" + try: + with open(filename) as f: + contents = f.read() + except EnvironmentError: + raise NotThisMethod("unable to read _version.py") + mo = re.search(r"version_json = '''\n(.*)''' # END VERSION_JSON", + contents, re.M | re.S) + if not mo: + mo = re.search(r"version_json = '''\r\n(.*)''' # END VERSION_JSON", + contents, re.M | re.S) + if not mo: + raise NotThisMethod("no version_json in _version.py") + return json.loads(mo.group(1)) + + +def write_to_version_file(filename, versions): + """Write the given version number to the given _version.py file.""" + os.unlink(filename) + contents = json.dumps(versions, sort_keys=True, + indent=1, separators=(",", ": ")) + with open(filename, "w") as f: + f.write(SHORT_VERSION_PY % contents) + + print("set %s to '%s'" % (filename, versions["version"])) + + +def plus_or_dot(pieces): + """Return a + if we don't already have one, else return a .""" + if "+" in pieces.get("closest-tag", ""): + return "." + return "+" + + +def render_pep440(pieces): + """Build up version string, with post-release "local version identifier". + + Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you + get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty + + Exceptions: + 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += plus_or_dot(pieces) + rendered += "%d.g%s" % (pieces["distance"], pieces["short"]) + if pieces["dirty"]: + rendered += ".dirty" + else: + # exception #1 + rendered = "0+untagged.%d.g%s" % (pieces["distance"], + pieces["short"]) + if pieces["dirty"]: + rendered += ".dirty" + return rendered + + +def render_pep440_pre(pieces): + """TAG[.post.devDISTANCE] -- No -dirty. + + Exceptions: + 1: no tags. 0.post.devDISTANCE + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"]: + rendered += ".post.dev%d" % pieces["distance"] + else: + # exception #1 + rendered = "0.post.dev%d" % pieces["distance"] + return rendered + + +def render_pep440_post(pieces): + """TAG[.postDISTANCE[.dev0]+gHEX] . + + The ".dev0" means dirty. Note that .dev0 sorts backwards + (a dirty tree will appear "older" than the corresponding clean one), + but you shouldn't be releasing software with -dirty anyways. + + Exceptions: + 1: no tags. 0.postDISTANCE[.dev0] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += ".post%d" % pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + rendered += plus_or_dot(pieces) + rendered += "g%s" % pieces["short"] + else: + # exception #1 + rendered = "0.post%d" % pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + rendered += "+g%s" % pieces["short"] + return rendered + + +def render_pep440_old(pieces): + """TAG[.postDISTANCE[.dev0]] . + + The ".dev0" means dirty. + + Eexceptions: + 1: no tags. 0.postDISTANCE[.dev0] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += ".post%d" % pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + else: + # exception #1 + rendered = "0.post%d" % pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + return rendered + + +def render_git_describe(pieces): + """TAG[-DISTANCE-gHEX][-dirty]. + + Like 'git describe --tags --dirty --always'. + + Exceptions: + 1: no tags. HEX[-dirty] (note: no 'g' prefix) + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"]: + rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) + else: + # exception #1 + rendered = pieces["short"] + if pieces["dirty"]: + rendered += "-dirty" + return rendered + + +def render_git_describe_long(pieces): + """TAG-DISTANCE-gHEX[-dirty]. + + Like 'git describe --tags --dirty --always -long'. + The distance/hash is unconditional. + + Exceptions: + 1: no tags. HEX[-dirty] (note: no 'g' prefix) + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) + else: + # exception #1 + rendered = pieces["short"] + if pieces["dirty"]: + rendered += "-dirty" + return rendered + + +def render(pieces, style): + """Render the given version pieces into the requested style.""" + if pieces["error"]: + return {"version": "unknown", + "full-revisionid": pieces.get("long"), + "dirty": None, + "error": pieces["error"], + "date": None} + + if not style or style == "default": + style = "pep440" # the default + + if style == "pep440": + rendered = render_pep440(pieces) + elif style == "pep440-pre": + rendered = render_pep440_pre(pieces) + elif style == "pep440-post": + rendered = render_pep440_post(pieces) + elif style == "pep440-old": + rendered = render_pep440_old(pieces) + elif style == "git-describe": + rendered = render_git_describe(pieces) + elif style == "git-describe-long": + rendered = render_git_describe_long(pieces) + else: + raise ValueError("unknown style '%s'" % style) + + return {"version": rendered, "full-revisionid": pieces["long"], + "dirty": pieces["dirty"], "error": None, + "date": pieces.get("date")} + + +class VersioneerBadRootError(Exception): + """The project root directory is unknown or missing key files.""" + + +def get_versions(verbose=False): + """Get the project version from whatever source is available. + + Returns dict with two keys: 'version' and 'full'. + """ + if "versioneer" in sys.modules: + # see the discussion in cmdclass.py:get_cmdclass() + del sys.modules["versioneer"] + + root = get_root() + cfg = get_config_from_root(root) + + assert cfg.VCS is not None, "please set [versioneer]VCS= in setup.cfg" + handlers = HANDLERS.get(cfg.VCS) + assert handlers, "unrecognized VCS '%s'" % cfg.VCS + verbose = verbose or cfg.verbose + assert cfg.versionfile_source is not None, \ + "please set versioneer.versionfile_source" + assert cfg.tag_prefix is not None, "please set versioneer.tag_prefix" + + versionfile_abs = os.path.join(root, cfg.versionfile_source) + + # extract version from first of: _version.py, VCS command (e.g. 'git + # describe'), parentdir. This is meant to work for developers using a + # source checkout, for users of a tarball created by 'setup.py sdist', + # and for users of a tarball/zipball created by 'git archive' or github's + # download-from-tag feature or the equivalent in other VCSes. + + get_keywords_f = handlers.get("get_keywords") + from_keywords_f = handlers.get("keywords") + if get_keywords_f and from_keywords_f: + try: + keywords = get_keywords_f(versionfile_abs) + ver = from_keywords_f(keywords, cfg.tag_prefix, verbose) + if verbose: + print("got version from expanded keyword %s" % ver) + return ver + except NotThisMethod: + pass + + try: + ver = versions_from_file(versionfile_abs) + if verbose: + print("got version from file %s %s" % (versionfile_abs, ver)) + return ver + except NotThisMethod: + pass + + from_vcs_f = handlers.get("pieces_from_vcs") + if from_vcs_f: + try: + pieces = from_vcs_f(cfg.tag_prefix, root, verbose) + ver = render(pieces, cfg.style) + if verbose: + print("got version from VCS %s" % ver) + return ver + except NotThisMethod: + pass + + try: + if cfg.parentdir_prefix: + ver = versions_from_parentdir(cfg.parentdir_prefix, root, verbose) + if verbose: + print("got version from parentdir %s" % ver) + return ver + except NotThisMethod: + pass + + if verbose: + print("unable to compute version") + + return {"version": "0+unknown", "full-revisionid": None, + "dirty": None, "error": "unable to compute version", + "date": None} + + +def get_version(): + """Get the short version string for this project.""" + return get_versions()["version"] + + +def get_cmdclass(): + """Get the custom setuptools/distutils subclasses used by Versioneer.""" + if "versioneer" in sys.modules: + del sys.modules["versioneer"] + # this fixes the "python setup.py develop" case (also 'install' and + # 'easy_install .'), in which subdependencies of the main project are + # built (using setup.py bdist_egg) in the same python process. Assume + # a main project A and a dependency B, which use different versions + # of Versioneer. A's setup.py imports A's Versioneer, leaving it in + # sys.modules by the time B's setup.py is executed, causing B to run + # with the wrong versioneer. Setuptools wraps the sub-dep builds in a + # sandbox that restores sys.modules to it's pre-build state, so the + # parent is protected against the child's "import versioneer". By + # removing ourselves from sys.modules here, before the child build + # happens, we protect the child from the parent's versioneer too. + # Also see https://github.com/warner/python-versioneer/issues/52 + + cmds = {} + + # we add "version" to both distutils and setuptools + from distutils.core import Command + + class cmd_version(Command): + description = "report generated version string" + user_options = [] + boolean_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + vers = get_versions(verbose=True) + print("Version: %s" % vers["version"]) + print(" full-revisionid: %s" % vers.get("full-revisionid")) + print(" dirty: %s" % vers.get("dirty")) + print(" date: %s" % vers.get("date")) + if vers["error"]: + print(" error: %s" % vers["error"]) + cmds["version"] = cmd_version + + # we override "build_py" in both distutils and setuptools + # + # most invocation pathways end up running build_py: + # distutils/build -> build_py + # distutils/install -> distutils/build ->.. + # setuptools/bdist_wheel -> distutils/install ->.. + # setuptools/bdist_egg -> distutils/install_lib -> build_py + # setuptools/install -> bdist_egg ->.. + # setuptools/develop -> ? + # pip install: + # copies source tree to a tempdir before running egg_info/etc + # if .git isn't copied too, 'git describe' will fail + # then does setup.py bdist_wheel, or sometimes setup.py install + # setup.py egg_info -> ? + + # we override different "build_py" commands for both environments + if "setuptools" in sys.modules: + from setuptools.command.build_py import build_py as _build_py + else: + from distutils.command.build_py import build_py as _build_py + + class cmd_build_py(_build_py): + def run(self): + root = get_root() + cfg = get_config_from_root(root) + versions = get_versions() + _build_py.run(self) + # now locate _version.py in the new build/ directory and replace + # it with an updated value + if cfg.versionfile_build: + target_versionfile = os.path.join(self.build_lib, + cfg.versionfile_build) + print("UPDATING %s" % target_versionfile) + write_to_version_file(target_versionfile, versions) + cmds["build_py"] = cmd_build_py + + if "cx_Freeze" in sys.modules: # cx_freeze enabled? + from cx_Freeze.dist import build_exe as _build_exe + # nczeczulin reports that py2exe won't like the pep440-style string + # as FILEVERSION, but it can be used for PRODUCTVERSION, e.g. + # setup(console=[{ + # "version": versioneer.get_version().split("+", 1)[0], # FILEVERSION + # "product_version": versioneer.get_version(), + # ... + + class cmd_build_exe(_build_exe): + def run(self): + root = get_root() + cfg = get_config_from_root(root) + versions = get_versions() + target_versionfile = cfg.versionfile_source + print("UPDATING %s" % target_versionfile) + write_to_version_file(target_versionfile, versions) + + _build_exe.run(self) + os.unlink(target_versionfile) + with open(cfg.versionfile_source, "w") as f: + LONG = LONG_VERSION_PY[cfg.VCS] + f.write(LONG % + {"DOLLAR": "$", + "STYLE": cfg.style, + "TAG_PREFIX": cfg.tag_prefix, + "PARENTDIR_PREFIX": cfg.parentdir_prefix, + "VERSIONFILE_SOURCE": cfg.versionfile_source, + }) + cmds["build_exe"] = cmd_build_exe + del cmds["build_py"] + + if 'py2exe' in sys.modules: # py2exe enabled? + try: + from py2exe.distutils_buildexe import py2exe as _py2exe # py3 + except ImportError: + from py2exe.build_exe import py2exe as _py2exe # py2 + + class cmd_py2exe(_py2exe): + def run(self): + root = get_root() + cfg = get_config_from_root(root) + versions = get_versions() + target_versionfile = cfg.versionfile_source + print("UPDATING %s" % target_versionfile) + write_to_version_file(target_versionfile, versions) + + _py2exe.run(self) + os.unlink(target_versionfile) + with open(cfg.versionfile_source, "w") as f: + LONG = LONG_VERSION_PY[cfg.VCS] + f.write(LONG % + {"DOLLAR": "$", + "STYLE": cfg.style, + "TAG_PREFIX": cfg.tag_prefix, + "PARENTDIR_PREFIX": cfg.parentdir_prefix, + "VERSIONFILE_SOURCE": cfg.versionfile_source, + }) + cmds["py2exe"] = cmd_py2exe + + # we override different "sdist" commands for both environments + if "setuptools" in sys.modules: + from setuptools.command.sdist import sdist as _sdist + else: + from distutils.command.sdist import sdist as _sdist + + class cmd_sdist(_sdist): + def run(self): + versions = get_versions() + self._versioneer_generated_versions = versions + # unless we update this, the command will keep using the old + # version + self.distribution.metadata.version = versions["version"] + return _sdist.run(self) + + def make_release_tree(self, base_dir, files): + root = get_root() + cfg = get_config_from_root(root) + _sdist.make_release_tree(self, base_dir, files) + # now locate _version.py in the new base_dir directory + # (remembering that it may be a hardlink) and replace it with an + # updated value + target_versionfile = os.path.join(base_dir, cfg.versionfile_source) + print("UPDATING %s" % target_versionfile) + write_to_version_file(target_versionfile, + self._versioneer_generated_versions) + cmds["sdist"] = cmd_sdist + + return cmds + + +CONFIG_ERROR = """ +setup.cfg is missing the necessary Versioneer configuration. You need +a section like: + + [versioneer] + VCS = git + style = pep440 + versionfile_source = src/myproject/_version.py + versionfile_build = myproject/_version.py + tag_prefix = + parentdir_prefix = myproject- + +You will also need to edit your setup.py to use the results: + + import versioneer + setup(version=versioneer.get_version(), + cmdclass=versioneer.get_cmdclass(), ...) + +Please read the docstring in ./versioneer.py for configuration instructions, +edit setup.cfg, and re-run the installer or 'python versioneer.py setup'. +""" + +SAMPLE_CONFIG = """ +# See the docstring in versioneer.py for instructions. Note that you must +# re-run 'versioneer.py setup' after changing this section, and commit the +# resulting files. + +[versioneer] +#VCS = git +#style = pep440 +#versionfile_source = +#versionfile_build = +#tag_prefix = +#parentdir_prefix = + +""" + +INIT_PY_SNIPPET = """ +from ._version import get_versions +__version__ = get_versions()['version'] +del get_versions +""" + + +def do_setup(): + """Main VCS-independent setup function for installing Versioneer.""" + root = get_root() + try: + cfg = get_config_from_root(root) + except (EnvironmentError, configparser.NoSectionError, + configparser.NoOptionError) as e: + if isinstance(e, (EnvironmentError, configparser.NoSectionError)): + print("Adding sample versioneer config to setup.cfg", + file=sys.stderr) + with open(os.path.join(root, "setup.cfg"), "a") as f: + f.write(SAMPLE_CONFIG) + print(CONFIG_ERROR, file=sys.stderr) + return 1 + + print(" creating %s" % cfg.versionfile_source) + with open(cfg.versionfile_source, "w") as f: + LONG = LONG_VERSION_PY[cfg.VCS] + f.write(LONG % {"DOLLAR": "$", + "STYLE": cfg.style, + "TAG_PREFIX": cfg.tag_prefix, + "PARENTDIR_PREFIX": cfg.parentdir_prefix, + "VERSIONFILE_SOURCE": cfg.versionfile_source, + }) + + ipy = os.path.join(os.path.dirname(cfg.versionfile_source), + "__init__.py") + if os.path.exists(ipy): + try: + with open(ipy, "r") as f: + old = f.read() + except EnvironmentError: + old = "" + if INIT_PY_SNIPPET not in old: + print(" appending to %s" % ipy) + with open(ipy, "a") as f: + f.write(INIT_PY_SNIPPET) + else: + print(" %s unmodified" % ipy) + else: + print(" %s doesn't exist, ok" % ipy) + ipy = None + + # Make sure both the top-level "versioneer.py" and versionfile_source + # (PKG/_version.py, used by runtime code) are in MANIFEST.in, so + # they'll be copied into source distributions. Pip won't be able to + # install the package without this. + manifest_in = os.path.join(root, "MANIFEST.in") + simple_includes = set() + try: + with open(manifest_in, "r") as f: + for line in f: + if line.startswith("include "): + for include in line.split()[1:]: + simple_includes.add(include) + except EnvironmentError: + pass + # That doesn't cover everything MANIFEST.in can do + # (http://docs.python.org/2/distutils/sourcedist.html#commands), so + # it might give some false negatives. Appending redundant 'include' + # lines is safe, though. + if "versioneer.py" not in simple_includes: + print(" appending 'versioneer.py' to MANIFEST.in") + with open(manifest_in, "a") as f: + f.write("include versioneer.py\n") + else: + print(" 'versioneer.py' already in MANIFEST.in") + if cfg.versionfile_source not in simple_includes: + print(" appending versionfile_source ('%s') to MANIFEST.in" % + cfg.versionfile_source) + with open(manifest_in, "a") as f: + f.write("include %s\n" % cfg.versionfile_source) + else: + print(" versionfile_source already in MANIFEST.in") + + # Make VCS-specific changes. For git, this means creating/changing + # .gitattributes to mark _version.py for export-subst keyword + # substitution. + do_vcs_install(manifest_in, cfg.versionfile_source, ipy) + return 0 + + +def scan_setup_py(): + """Validate the contents of setup.py against Versioneer's expectations.""" + found = set() + setters = False + errors = 0 + with open("setup.py", "r") as f: + for line in f.readlines(): + if "import versioneer" in line: + found.add("import") + if "versioneer.get_cmdclass()" in line: + found.add("cmdclass") + if "versioneer.get_version()" in line: + found.add("get_version") + if "versioneer.VCS" in line: + setters = True + if "versioneer.versionfile_source" in line: + setters = True + if len(found) != 3: + print("") + print("Your setup.py appears to be missing some important items") + print("(but I might be wrong). Please make sure it has something") + print("roughly like the following:") + print("") + print(" import versioneer") + print(" setup( version=versioneer.get_version(),") + print(" cmdclass=versioneer.get_cmdclass(), ...)") + print("") + errors += 1 + if setters: + print("You should remove lines like 'versioneer.VCS = ' and") + print("'versioneer.versionfile_source = ' . This configuration") + print("now lives in setup.cfg, and should be removed from setup.py") + print("") + errors += 1 + return errors + + +if __name__ == "__main__": + cmd = sys.argv[1] + if cmd == "setup": + errors = do_setup() + errors += scan_setup_py() + if errors: + sys.exit(1)