From 093df24620e61c51cf40973f1e706cff2dac0bcc Mon Sep 17 00:00:00 2001 From: Tieqiong Zhang Date: Tue, 2 Jul 2024 12:05:18 -0400 Subject: [PATCH 01/21] add Untracked files --- .flake8 | 11 + .github/workflows/docs.yml | 43 +++ .github/workflows/main.yml | 54 ++++ .github/workflows/pre-commit.yml | 19 ++ .isort.cfg | 4 + .pre-commit-config.yaml | 43 +++ AUTHORS.rst | 10 + CHANGELOG.rst | 5 + CODE_OF_CONDUCT.rst | 133 ++++++++ doc/make.bat | 36 +++ doc/source/_static/.placeholder | 0 .../api/diffpy.srfit.equation.literals.rst | 46 +++ doc/source/api/diffpy.srfit.equation.rst | 38 +++ .../api/diffpy.srfit.equation.visitors.rst | 54 ++++ .../api/diffpy.srfit.example_package.rst | 31 ++ doc/source/api/diffpy.srfit.fitbase.rst | 142 +++++++++ doc/source/api/diffpy.srfit.interface.rst | 22 ++ doc/source/api/diffpy.srfit.pdf.rst | 62 ++++ doc/source/api/diffpy.srfit.rst | 30 ++ doc/source/api/diffpy.srfit.sas.rst | 54 ++++ doc/source/api/diffpy.srfit.structure.rst | 70 +++++ doc/source/api/diffpy.srfit.util.rst | 46 +++ doc/source/conf.py | 289 ++++++++++++++++++ doc/source/examples.rst | 56 ++++ doc/source/examples/coreshellnp.rst | 7 + doc/source/examples/crystalpdf.rst | 7 + doc/source/examples/crystalpdfall.rst | 7 + doc/source/examples/crystalpdfobjcryst.rst | 7 + doc/source/examples/crystalpdftwodata.rst | 7 + doc/source/examples/crystalpdftwophase.rst | 7 + doc/source/examples/debyemodel.rst | 7 + doc/source/examples/debyemodelII.rst | 7 + doc/source/examples/ellipsoidsas.rst | 7 + doc/source/examples/gaussiangenerator.rst | 7 + doc/source/examples/gaussianrecipe.rst | 7 + doc/source/examples/interface.rst | 7 + doc/source/examples/npintensity.rst | 7 + doc/source/examples/npintensityII.rst | 7 + doc/source/examples/nppdfcrystal.rst | 7 + doc/source/examples/nppdfobjcryst.rst | 7 + doc/source/examples/nppdfsas.rst | 7 + doc/source/examples/simplepdf.rst | 7 + doc/source/examples/simplepdftwophase.rst | 7 + doc/source/examples/simplerecipe.rst | 7 + doc/source/extending.rst | 267 ++++++++++++++++ doc/source/index.rst | 44 +++ doc/source/license.rst | 39 +++ doc/source/release.rst | 5 + news/TEMPLATE.rst | 23 ++ requirements/README.txt | 11 + requirements/build.txt | 2 + requirements/docs.txt | 4 + requirements/pip.txt | 0 requirements/run.txt | 0 requirements/test.txt | 5 + src/diffpy/srfit/tests/conftest.py | 19 ++ 56 files changed, 1857 insertions(+) create mode 100644 .flake8 create mode 100644 .github/workflows/docs.yml create mode 100644 .github/workflows/main.yml create mode 100644 .github/workflows/pre-commit.yml create mode 100644 .isort.cfg create mode 100644 .pre-commit-config.yaml create mode 100644 AUTHORS.rst create mode 100644 CHANGELOG.rst create mode 100644 CODE_OF_CONDUCT.rst create mode 100644 doc/make.bat create mode 100644 doc/source/_static/.placeholder create mode 100644 doc/source/api/diffpy.srfit.equation.literals.rst create mode 100644 doc/source/api/diffpy.srfit.equation.rst create mode 100644 doc/source/api/diffpy.srfit.equation.visitors.rst create mode 100644 doc/source/api/diffpy.srfit.example_package.rst create mode 100644 doc/source/api/diffpy.srfit.fitbase.rst create mode 100644 doc/source/api/diffpy.srfit.interface.rst create mode 100644 doc/source/api/diffpy.srfit.pdf.rst create mode 100644 doc/source/api/diffpy.srfit.rst create mode 100644 doc/source/api/diffpy.srfit.sas.rst create mode 100644 doc/source/api/diffpy.srfit.structure.rst create mode 100644 doc/source/api/diffpy.srfit.util.rst create mode 100644 doc/source/conf.py create mode 100644 doc/source/examples.rst create mode 100644 doc/source/examples/coreshellnp.rst create mode 100644 doc/source/examples/crystalpdf.rst create mode 100644 doc/source/examples/crystalpdfall.rst create mode 100644 doc/source/examples/crystalpdfobjcryst.rst create mode 100644 doc/source/examples/crystalpdftwodata.rst create mode 100644 doc/source/examples/crystalpdftwophase.rst create mode 100644 doc/source/examples/debyemodel.rst create mode 100644 doc/source/examples/debyemodelII.rst create mode 100644 doc/source/examples/ellipsoidsas.rst create mode 100644 doc/source/examples/gaussiangenerator.rst create mode 100644 doc/source/examples/gaussianrecipe.rst create mode 100644 doc/source/examples/interface.rst create mode 100644 doc/source/examples/npintensity.rst create mode 100644 doc/source/examples/npintensityII.rst create mode 100644 doc/source/examples/nppdfcrystal.rst create mode 100644 doc/source/examples/nppdfobjcryst.rst create mode 100644 doc/source/examples/nppdfsas.rst create mode 100644 doc/source/examples/simplepdf.rst create mode 100644 doc/source/examples/simplepdftwophase.rst create mode 100644 doc/source/examples/simplerecipe.rst create mode 100644 doc/source/extending.rst create mode 100644 doc/source/index.rst create mode 100644 doc/source/license.rst create mode 100644 doc/source/release.rst create mode 100644 news/TEMPLATE.rst create mode 100644 requirements/README.txt create mode 100644 requirements/build.txt create mode 100644 requirements/docs.txt create mode 100644 requirements/pip.txt create mode 100644 requirements/run.txt create mode 100644 requirements/test.txt create mode 100644 src/diffpy/srfit/tests/conftest.py diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..2d2cb168 --- /dev/null +++ b/.flake8 @@ -0,0 +1,11 @@ +[flake8] +exclude = + .git, + __pycache__, + build, + dist, + doc/source/conf.py +max-line-length = 115 +# Ignore some style 'errors' produced while formatting by 'black' +# https://black.readthedocs.io/en/stable/guides/using_black_with_other_tools.html#labels-why-pycodestyle-warnings +extend-ignore = E203 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 00000000..a4661f5c --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,43 @@ +name: Build Documentation + +on: + push: + branches: + - main + release: + +jobs: + test: + runs-on: ubuntu-latest + defaults: + run: + shell: bash -l {0} + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - uses: conda-incubator/setup-miniconda@v2 + with: + activate-environment: build + auto-update-conda: true + + - name: install requirements + run: >- + conda install -n build -c conda-forge + --file requirements/build.txt + --file requirements/run.txt + --file requirements/docs.txt + --quiet --yes + + - name: install the package + run: python -m pip install . --no-deps + + - name: build documents + run: make -C doc html + + - name: Deploy + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./doc/build/html diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..c74ba5b9 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,54 @@ +name: CI + +on: + push: + branches: + - main + - CI + pull_request: + workflow_dispatch: + +jobs: + miniconda: + name: Miniconda ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: ["ubuntu-latest"] + steps: + - name: check out diffpy.srfit + uses: actions/checkout@v3 + with: + repository: diffpy/diffpy.srfit + path: . + fetch-depth: 0 # avoid shallow clone with no tags + + - name: initialize miniconda + # this uses a marketplace action that sets up miniconda in a way that makes + # it easier to use. I tried setting it up without this and it was a pain + uses: conda-incubator/setup-miniconda@v2 + with: + activate-environment: test + # environment.yml file is needed by this action. Because I don't want + # maintain this but rather maintain the requirements files it just has + # basic things in it like conda and pip + environment-file: ./environment.yml + python-version: 3 + auto-activate-base: false + + - name: install diffpy.srfit requirements + shell: bash -l {0} + run: | + conda config --set always_yes yes --set changeps1 no + conda config --add channels conda-forge + conda activate test + conda install --file requirements/run.txt + conda install --file requirements/test.txt + pip install . + - name: Validate diffpy.srfit + shell: bash -l {0} + run: | + conda activate test + coverage run -m pytest -vv -s + coverage report -m + codecov diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 00000000..f2ff7e42 --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,19 @@ +name: pre-commit + +on: + pull_request: + push: + workflow_dispatch: + +jobs: + pre-commit: + # pull requests are a duplicate of a branch push if within the same repo. + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository + + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + - uses: pre-commit/action@v3.0.0 + with: + extra_args: --all-files diff --git a/.isort.cfg b/.isort.cfg new file mode 100644 index 00000000..e0926f42 --- /dev/null +++ b/.isort.cfg @@ -0,0 +1,4 @@ +[settings] +line_length = 115 +multi_line_output = 3 +include_trailing_comma = True diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..c4588061 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,43 @@ +default_language_version: + python: python3 +ci: + autofix_commit_msg: | + [pre-commit.ci] auto fixes from pre-commit hooks + autofix_prs: true + autoupdate_branch: 'pre-commit-autoupdate' + autoupdate_commit_msg: '[pre-commit.ci] pre-commit autoupdate' + autoupdate_schedule: monthly + skip: [no-commit-to-branch] + submodules: false +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + exclude: '\.(rst|txt)$' + - repo: https://github.com/psf/black + rev: 24.4.2 + hooks: + - id: black + - repo: https://github.com/pycqa/flake8 + rev: 7.0.0 + hooks: + - id: flake8 + - repo: https://github.com/pycqa/isort + rev: 5.13.2 + hooks: + - id: isort + args: ["--profile", "black"] + - repo: https://github.com/kynan/nbstripout + rev: 0.7.1 + hooks: + - id: nbstripout + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: no-commit-to-branch + name: Prevent Commit to Main Branch + args: ["--branch", "main"] + stages: [pre-commit] diff --git a/AUTHORS.rst b/AUTHORS.rst new file mode 100644 index 00000000..9f3f16dc --- /dev/null +++ b/AUTHORS.rst @@ -0,0 +1,10 @@ +Authors +======= + +Billinge Group and community contibutors. + +Contributors +------------ + +For a list of contributors, visit +https://github.com/diffpy/diffpy.srfit/graphs/contributors diff --git a/CHANGELOG.rst b/CHANGELOG.rst new file mode 100644 index 00000000..26694512 --- /dev/null +++ b/CHANGELOG.rst @@ -0,0 +1,5 @@ +============= +Release Notes +============= + +.. current developments diff --git a/CODE_OF_CONDUCT.rst b/CODE_OF_CONDUCT.rst new file mode 100644 index 00000000..ff9c3561 --- /dev/null +++ b/CODE_OF_CONDUCT.rst @@ -0,0 +1,133 @@ +===================================== + Contributor Covenant Code of Conduct +===================================== + +Our Pledge +---------- + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +Our Standards +------------- + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +Enforcement Responsibilities +---------------------------- + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders 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, and will communicate reasons for moderation +decisions when appropriate. + +Scope +----- + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official email address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +Enforcement +----------- + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +sb2896@columbia.edu. All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +Enforcement Guidelines +---------------------- + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +1. Correction +**************** + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +2. Warning +************* + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +3. Temporary Ban +****************** + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +4. Permanent Ban +****************** + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +Attribution +----------- + +This Code of Conduct is adapted from the `Contributor Covenant `_. + +Community Impact Guidelines were inspired by `Mozilla's code of conduct enforcement ladder `_. + +For answers to common questions about this code of conduct, see the `FAQ `_. `Translations are available `_ diff --git a/doc/make.bat b/doc/make.bat new file mode 100644 index 00000000..ac53d5bd --- /dev/null +++ b/doc/make.bat @@ -0,0 +1,36 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build +set SPHINXPROJ=PackagingScientificPython + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% + +:end +popd diff --git a/doc/source/_static/.placeholder b/doc/source/_static/.placeholder new file mode 100644 index 00000000..e69de29b diff --git a/doc/source/api/diffpy.srfit.equation.literals.rst b/doc/source/api/diffpy.srfit.equation.literals.rst new file mode 100644 index 00000000..35b905b1 --- /dev/null +++ b/doc/source/api/diffpy.srfit.equation.literals.rst @@ -0,0 +1,46 @@ +diffpy.srfit.equation.literals package +====================================== + +Submodules +---------- + +diffpy.srfit.equation.literals.abcs module +------------------------------------------ + +.. automodule:: diffpy.srfit.equation.literals.abcs + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.equation.literals.argument module +---------------------------------------------- + +.. automodule:: diffpy.srfit.equation.literals.argument + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.equation.literals.literal module +--------------------------------------------- + +.. automodule:: diffpy.srfit.equation.literals.literal + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.equation.literals.operators module +----------------------------------------------- + +.. automodule:: diffpy.srfit.equation.literals.operators + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: diffpy.srfit.equation.literals + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/api/diffpy.srfit.equation.rst b/doc/source/api/diffpy.srfit.equation.rst new file mode 100644 index 00000000..f5642da1 --- /dev/null +++ b/doc/source/api/diffpy.srfit.equation.rst @@ -0,0 +1,38 @@ +diffpy.srfit.equation package +============================= + +Subpackages +----------- + +.. toctree:: + + diffpy.srfit.equation.literals + diffpy.srfit.equation.visitors + +Submodules +---------- + +diffpy.srfit.equation.builder module +------------------------------------ + +.. automodule:: diffpy.srfit.equation.builder + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.equation.equationmod module +---------------------------------------- + +.. automodule:: diffpy.srfit.equation.equationmod + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: diffpy.srfit.equation + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/api/diffpy.srfit.equation.visitors.rst b/doc/source/api/diffpy.srfit.equation.visitors.rst new file mode 100644 index 00000000..de17f93d --- /dev/null +++ b/doc/source/api/diffpy.srfit.equation.visitors.rst @@ -0,0 +1,54 @@ +diffpy.srfit.equation.visitors package +====================================== + +Submodules +---------- + +diffpy.srfit.equation.visitors.argfinder module +----------------------------------------------- + +.. automodule:: diffpy.srfit.equation.visitors.argfinder + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.equation.visitors.printer module +--------------------------------------------- + +.. automodule:: diffpy.srfit.equation.visitors.printer + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.equation.visitors.swapper module +--------------------------------------------- + +.. automodule:: diffpy.srfit.equation.visitors.swapper + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.equation.visitors.validator module +----------------------------------------------- + +.. automodule:: diffpy.srfit.equation.visitors.validator + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.equation.visitors.visitor module +--------------------------------------------- + +.. automodule:: diffpy.srfit.equation.visitors.visitor + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: diffpy.srfit.equation.visitors + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/api/diffpy.srfit.example_package.rst b/doc/source/api/diffpy.srfit.example_package.rst new file mode 100644 index 00000000..60910070 --- /dev/null +++ b/doc/source/api/diffpy.srfit.example_package.rst @@ -0,0 +1,31 @@ +.. _example_package documentation: + +|title| +======= + +.. |title| replace:: diffpy.srfit.example_package package + +.. automodule:: diffpy.srfit.example_package + :members: + :undoc-members: + :show-inheritance: + +|foo| +----- + +.. |foo| replace:: diffpy.srfit.example_package.foo module + +.. automodule:: diffpy.srfit.example_package.foo + :members: + :undoc-members: + :show-inheritance: + +|bar| +----- + +.. |bar| replace:: diffpy.srfit.example_package.bar module + +.. automodule:: diffpy.srfit.example_package.foo + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/api/diffpy.srfit.fitbase.rst b/doc/source/api/diffpy.srfit.fitbase.rst new file mode 100644 index 00000000..44093442 --- /dev/null +++ b/doc/source/api/diffpy.srfit.fitbase.rst @@ -0,0 +1,142 @@ +diffpy.srfit.fitbase package +============================ + +Submodules +---------- + +diffpy.srfit.fitbase.calculator module +-------------------------------------- + +.. automodule:: diffpy.srfit.fitbase.calculator + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.fitbase.configurable module +---------------------------------------- + +.. automodule:: diffpy.srfit.fitbase.configurable + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.fitbase.constraint module +-------------------------------------- + +.. automodule:: diffpy.srfit.fitbase.constraint + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.fitbase.fitcontribution module +------------------------------------------- + +.. automodule:: diffpy.srfit.fitbase.fitcontribution + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.fitbase.fithook module +----------------------------------- + +.. automodule:: diffpy.srfit.fitbase.fithook + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.fitbase.fitrecipe module +------------------------------------- + +.. automodule:: diffpy.srfit.fitbase.fitrecipe + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.fitbase.fitresults module +-------------------------------------- + +.. automodule:: diffpy.srfit.fitbase.fitresults + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.fitbase.parameter module +------------------------------------- + +.. automodule:: diffpy.srfit.fitbase.parameter + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.fitbase.parameterset module +---------------------------------------- + +.. automodule:: diffpy.srfit.fitbase.parameterset + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.fitbase.profile module +----------------------------------- + +.. automodule:: diffpy.srfit.fitbase.profile + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.fitbase.profilegenerator module +-------------------------------------------- + +.. automodule:: diffpy.srfit.fitbase.profilegenerator + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.fitbase.profileparser module +----------------------------------------- + +.. automodule:: diffpy.srfit.fitbase.profileparser + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.fitbase.recipeorganizer module +------------------------------------------- + +.. automodule:: diffpy.srfit.fitbase.recipeorganizer + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.fitbase.restraint module +------------------------------------- + +.. automodule:: diffpy.srfit.fitbase.restraint + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.fitbase.simplerecipe module +---------------------------------------- + +.. automodule:: diffpy.srfit.fitbase.simplerecipe + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.fitbase.validatable module +--------------------------------------- + +.. automodule:: diffpy.srfit.fitbase.validatable + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: diffpy.srfit.fitbase + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/api/diffpy.srfit.interface.rst b/doc/source/api/diffpy.srfit.interface.rst new file mode 100644 index 00000000..4b6296a8 --- /dev/null +++ b/doc/source/api/diffpy.srfit.interface.rst @@ -0,0 +1,22 @@ +diffpy.srfit.interface package +============================== + +Submodules +---------- + +diffpy.srfit.interface.interface module +--------------------------------------- + +.. automodule:: diffpy.srfit.interface.interface + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: diffpy.srfit.interface + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/api/diffpy.srfit.pdf.rst b/doc/source/api/diffpy.srfit.pdf.rst new file mode 100644 index 00000000..a336a375 --- /dev/null +++ b/doc/source/api/diffpy.srfit.pdf.rst @@ -0,0 +1,62 @@ +diffpy.srfit.pdf package +======================== + +Submodules +---------- + +diffpy.srfit.pdf.basepdfgenerator module +---------------------------------------- + +.. automodule:: diffpy.srfit.pdf.basepdfgenerator + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.pdf.characteristicfunctions module +----------------------------------------------- + +.. automodule:: diffpy.srfit.pdf.characteristicfunctions + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.pdf.debyepdfgenerator module +----------------------------------------- + +.. automodule:: diffpy.srfit.pdf.debyepdfgenerator + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.pdf.pdfcontribution module +--------------------------------------- + +.. automodule:: diffpy.srfit.pdf.pdfcontribution + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.pdf.pdfgenerator module +------------------------------------ + +.. automodule:: diffpy.srfit.pdf.pdfgenerator + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.pdf.pdfparser module +--------------------------------- + +.. automodule:: diffpy.srfit.pdf.pdfparser + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: diffpy.srfit.pdf + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/api/diffpy.srfit.rst b/doc/source/api/diffpy.srfit.rst new file mode 100644 index 00000000..5b2b697b --- /dev/null +++ b/doc/source/api/diffpy.srfit.rst @@ -0,0 +1,30 @@ +:tocdepth: -1 + +|title| +======= + +.. |title| replace:: diffpy.srfit package + +.. automodule:: diffpy.srfit + :members: + :undoc-members: + :show-inheritance: + +Subpackages +----------- + +.. toctree:: + diffpy.srfit.example_package + +Submodules +---------- + +|module| +-------- + +.. |module| replace:: diffpy.srfit.example_submodule module + +.. automodule:: diffpy.srfit.example_submodule + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/api/diffpy.srfit.sas.rst b/doc/source/api/diffpy.srfit.sas.rst new file mode 100644 index 00000000..40f24b3d --- /dev/null +++ b/doc/source/api/diffpy.srfit.sas.rst @@ -0,0 +1,54 @@ +diffpy.srfit.sas package +======================== + +Submodules +---------- + +diffpy.srfit.sas.prcalculator module +------------------------------------ + +.. automodule:: diffpy.srfit.sas.prcalculator + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.sas.sasgenerator module +------------------------------------ + +.. automodule:: diffpy.srfit.sas.sasgenerator + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.sas.sasparameter module +------------------------------------ + +.. automodule:: diffpy.srfit.sas.sasparameter + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.sas.sasparser module +--------------------------------- + +.. automodule:: diffpy.srfit.sas.sasparser + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.sas.sasprofile module +---------------------------------- + +.. automodule:: diffpy.srfit.sas.sasprofile + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: diffpy.srfit.sas + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/api/diffpy.srfit.structure.rst b/doc/source/api/diffpy.srfit.structure.rst new file mode 100644 index 00000000..1bb5dd22 --- /dev/null +++ b/doc/source/api/diffpy.srfit.structure.rst @@ -0,0 +1,70 @@ +diffpy.srfit.structure package +============================== + +Submodules +---------- + +diffpy.srfit.structure.basestructureparset module +------------------------------------------------- + +.. automodule:: diffpy.srfit.structure.basestructureparset + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.structure.bvsrestraint module +------------------------------------------ + +.. automodule:: diffpy.srfit.structure.bvsrestraint + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.structure.cctbxparset module +----------------------------------------- + +.. automodule:: diffpy.srfit.structure.cctbxparset + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.structure.diffpyparset module +------------------------------------------ + +.. automodule:: diffpy.srfit.structure.diffpyparset + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.structure.objcrystparset module +-------------------------------------------- + +.. automodule:: diffpy.srfit.structure.objcrystparset + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.structure.sgconstraints module +------------------------------------------- + +.. automodule:: diffpy.srfit.structure.sgconstraints + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.structure.srrealparset module +------------------------------------------ + +.. automodule:: diffpy.srfit.structure.srrealparset + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: diffpy.srfit.structure + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/api/diffpy.srfit.util.rst b/doc/source/api/diffpy.srfit.util.rst new file mode 100644 index 00000000..64541ce6 --- /dev/null +++ b/doc/source/api/diffpy.srfit.util.rst @@ -0,0 +1,46 @@ +diffpy.srfit.util package +========================= + +Submodules +---------- + +diffpy.srfit.util.inpututils module +----------------------------------- + +.. automodule:: diffpy.srfit.util.inpututils + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.util.nameutils module +---------------------------------- + +.. automodule:: diffpy.srfit.util.nameutils + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.util.observable module +----------------------------------- + +.. automodule:: diffpy.srfit.util.observable + :members: + :undoc-members: + :show-inheritance: + +diffpy.srfit.util.tagmanager module +----------------------------------- + +.. automodule:: diffpy.srfit.util.tagmanager + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: diffpy.srfit.util + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/conf.py b/doc/source/conf.py new file mode 100644 index 00000000..e7654b23 --- /dev/null +++ b/doc/source/conf.py @@ -0,0 +1,289 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# diffpy.srfit documentation build configuration file, created by +# sphinx-quickstart on Thu Jan 30 15:49:41 2014. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import time +from importlib.metadata import version +from pathlib import Path + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use Path().resolve() to make it absolute, like shown here. +# sys.path.insert(0, str(Path(".").resolve())) +sys.path.insert(0, str(Path("../..").resolve())) +sys.path.insert(0, str(Path("../../src").resolve())) + +# abbreviations +ab_authors = "Billinge Group members and community contributors" + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + "sphinx.ext.autodoc", + "sphinx.ext.napoleon", + "sphinx.ext.todo", + "sphinx.ext.viewcode", + "sphinx.ext.intersphinx", + "sphinx_rtd_theme", + "m2r", +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +source_suffix = [".rst", ".md"] + +# The encoding of source files. +# source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = "index" + +# General information about the project. +project = "diffpy.srfit" +copyright = "%Y, The Trustees of Columbia University in the City of New York" + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. + +fullversion = version(project) +# The short X.Y version. +version = "".join(fullversion.split(".post")[:1]) +# The full version, including alpha/beta/rc tags. +release = fullversion + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +# today = '' +today = time.strftime("%B %d, %Y", time.localtime()) +year = today.split()[-1] +# Else, today_fmt is used as the format for a strftime call. +# today_fmt = '%B %d, %Y' +# substitute YEAR in the copyright string +copyright = copyright.replace("%Y", year) + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ["build"] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +# default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +# add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +# add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +# show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = "sphinx" + +# A list of ignored prefixes for module index sorting. +modindex_common_prefix = ["diffpy.srfit"] + +# Display all warnings for missing links. +nitpicky = True + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "sphinx_rtd_theme" + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +html_theme_options = { + "navigation_with_keys": "true", +} + +# Add any paths that contain custom themes here, relative to this directory. +# html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +# html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +# html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +# html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +# html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +# html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +# html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +# html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +# html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +# html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +# html_additional_pages = {} + +# If false, no module index is generated. +# html_domain_indices = True + +# If false, no index is generated. +# html_use_index = True + +# If true, the index is split into individual pages for each letter. +# html_split_index = False + +# If true, links to the reST sources are added to the pages. +# html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +# html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +# html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +# html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +# html_file_suffix = None + +# Output file base name for HTML help builder. +basename = "diffpy.srfit".replace(" ", "").replace(".", "") +htmlhelp_basename = basename + "doc" + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # 'papersize': 'letterpaper', + # The font size ('10pt', '11pt' or '12pt'). + # 'pointsize': '10pt', + # Additional stuff for the LaTeX preamble. + # 'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + ("index", "diffpy.srfit.tex", "diffpy.srfit Documentation", ab_authors, "manual"), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +# latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +# latex_use_parts = False + +# If true, show page references after internal links. +# latex_show_pagerefs = False + +# If true, show URL addresses after external links. +# latex_show_urls = False + +# Documents to append as an appendix to all manuals. +# latex_appendices = [] + +# If false, no module index is generated. +# latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [("index", "diffpy.srfit", "diffpy.srfit Documentation", ab_authors, 1)] + +# If true, show URL addresses after external links. +# man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ( + "index", + "diffpy.srfit", + "diffpy.srfit Documentation", + ab_authors, + "diffpy.srfit", + "One line description of project.", + "Miscellaneous", + ), +] + +# Documents to append as an appendix to all manuals. +# texinfo_appendices = [] + +# If false, no module index is generated. +# texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +# texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +# texinfo_no_detailmenu = False + + +# Example configuration for intersphinx: refer to the Python standard library. +# intersphinx_mapping = {'http://docs.python.org/': None} diff --git a/doc/source/examples.rst b/doc/source/examples.rst new file mode 100644 index 00000000..2403d1b8 --- /dev/null +++ b/doc/source/examples.rst @@ -0,0 +1,56 @@ +.. _developers-guide-examples: + +=================== +Examples +=================== + +.. include:: ../../examples/README + +.. This creates the links from the filenames within README to pages. +.. _gaussianrecipe.py: examples/gaussianrecipe.html +.. _debyemodel.py: examples/debyemodel.html +.. _debyemodelII.py: examples/debyemodelII.html +.. _gaussiangenerator.py: examples/gaussiangenerator.html +.. _npintensity.py: examples/npintensity.html +.. _npintensityII.py: examples/npintensityII.html +.. _nppdfobjcryst.py: examples/nppdfobjcryst.html +.. _crystalpdf.py: examples/crystalpdf.html +.. _simplepdf.py: examples/simplepdf.html +.. _crystalpdfobjcryst.py: examples/crystalpdfobjcryst.html +.. _crystalpdftwophase.py: examples/crystalpdftwophase.html +.. _simplepdftwophase.py: examples/simplepdftwophase.html +.. _crystalpdftwodata.py: examples/crystalpdftwodata.html +.. _crystalpdfall.py: examples/crystalpdfall.html +.. _nppdfcrystal.py: examples/nppdfcrystal.html +.. _coreshellnp.py: examples/coreshellnp.html +.. _ellipsoidsas.py: examples/ellipsoidsas.html +.. _nppdfsas.py: examples/nppdfsas.html +.. _interface.py: examples/interface.html +.. _simplerecipe.py: examples/simplerecipe.html + + +Files +---------- + +.. toctree:: + + examples/gaussianrecipe.rst + examples/debyemodel.rst + examples/debyemodelII.rst + examples/gaussiangenerator.rst + examples/npintensity.rst + examples/npintensityII.rst + examples/nppdfobjcryst.rst + examples/crystalpdf.rst + examples/simplepdf.rst + examples/crystalpdfobjcryst.rst + examples/crystalpdftwophase.rst + examples/simplepdftwophase.rst + examples/crystalpdftwodata.rst + examples/crystalpdfall.rst + examples/nppdfcrystal.rst + examples/coreshellnp.rst + examples/ellipsoidsas.rst + examples/nppdfsas.rst + examples/interface.rst + examples/simplerecipe.rst diff --git a/doc/source/examples/coreshellnp.rst b/doc/source/examples/coreshellnp.rst new file mode 100644 index 00000000..d8a84e0f --- /dev/null +++ b/doc/source/examples/coreshellnp.rst @@ -0,0 +1,7 @@ +.. _coreshellnp.py: + +======================== +coreshellnp.py +======================== + +.. literalinclude:: ../../../examples/coreshellnp.py diff --git a/doc/source/examples/crystalpdf.rst b/doc/source/examples/crystalpdf.rst new file mode 100644 index 00000000..51ef5185 --- /dev/null +++ b/doc/source/examples/crystalpdf.rst @@ -0,0 +1,7 @@ +.. _crystalpdf.py: + +======================== +crystalpdf.py +======================== + +.. literalinclude:: ../../../examples/crystalpdf.py diff --git a/doc/source/examples/crystalpdfall.rst b/doc/source/examples/crystalpdfall.rst new file mode 100644 index 00000000..b2f74fb8 --- /dev/null +++ b/doc/source/examples/crystalpdfall.rst @@ -0,0 +1,7 @@ +.. _crystalpdfall.py: + +======================== +crystalpdfall.py +======================== + +.. literalinclude:: ../../../examples/crystalpdfall.py diff --git a/doc/source/examples/crystalpdfobjcryst.rst b/doc/source/examples/crystalpdfobjcryst.rst new file mode 100644 index 00000000..4542b65a --- /dev/null +++ b/doc/source/examples/crystalpdfobjcryst.rst @@ -0,0 +1,7 @@ +.. _crystalpdfobjcryst.py: + +======================== +crystalpdfobjcryst.py +======================== + +.. literalinclude:: ../../../examples/crystalpdfobjcryst.py diff --git a/doc/source/examples/crystalpdftwodata.rst b/doc/source/examples/crystalpdftwodata.rst new file mode 100644 index 00000000..9b42e45f --- /dev/null +++ b/doc/source/examples/crystalpdftwodata.rst @@ -0,0 +1,7 @@ +.. _crystalpdftwodata.py: + +======================== +crystalpdftwodata.py +======================== + +.. literalinclude:: ../../../examples/crystalpdftwodata.py diff --git a/doc/source/examples/crystalpdftwophase.rst b/doc/source/examples/crystalpdftwophase.rst new file mode 100644 index 00000000..eb2cf18b --- /dev/null +++ b/doc/source/examples/crystalpdftwophase.rst @@ -0,0 +1,7 @@ +.. _crystalpdftwophase.py: + +======================== +crystalpdftwophase.py +======================== + +.. literalinclude:: ../../../examples/crystalpdftwophase.py diff --git a/doc/source/examples/debyemodel.rst b/doc/source/examples/debyemodel.rst new file mode 100644 index 00000000..436d20ca --- /dev/null +++ b/doc/source/examples/debyemodel.rst @@ -0,0 +1,7 @@ +.. _debyemodel.py: + +======================== +debyemodel.py +======================== + +.. literalinclude:: ../../../examples/debyemodel.py diff --git a/doc/source/examples/debyemodelII.rst b/doc/source/examples/debyemodelII.rst new file mode 100644 index 00000000..d44cc60d --- /dev/null +++ b/doc/source/examples/debyemodelII.rst @@ -0,0 +1,7 @@ +.. _debyemodelII.py: + +======================== +debyemodelII.py +======================== + +.. literalinclude:: ../../../examples/debyemodelII.py diff --git a/doc/source/examples/ellipsoidsas.rst b/doc/source/examples/ellipsoidsas.rst new file mode 100644 index 00000000..132b2ee7 --- /dev/null +++ b/doc/source/examples/ellipsoidsas.rst @@ -0,0 +1,7 @@ +.. _ellipsoidsas.py: + +======================== +ellipsoidsas.py +======================== + +.. literalinclude:: ../../../examples/ellipsoidsas.py diff --git a/doc/source/examples/gaussiangenerator.rst b/doc/source/examples/gaussiangenerator.rst new file mode 100644 index 00000000..eb101bb9 --- /dev/null +++ b/doc/source/examples/gaussiangenerator.rst @@ -0,0 +1,7 @@ +.. _gaussiangenerator.py: + +======================== +gaussiangenerator.py +======================== + +.. literalinclude:: ../../../examples/gaussiangenerator.py diff --git a/doc/source/examples/gaussianrecipe.rst b/doc/source/examples/gaussianrecipe.rst new file mode 100644 index 00000000..73f94eac --- /dev/null +++ b/doc/source/examples/gaussianrecipe.rst @@ -0,0 +1,7 @@ +.. _gaussianrecipe.py: + +======================== +gaussianrecipe.py +======================== + +.. literalinclude:: ../../../examples/gaussianrecipe.py diff --git a/doc/source/examples/interface.rst b/doc/source/examples/interface.rst new file mode 100644 index 00000000..41e706a8 --- /dev/null +++ b/doc/source/examples/interface.rst @@ -0,0 +1,7 @@ +.. _interface.py: + +======================== +interface.py +======================== + +.. literalinclude:: ../../../examples/interface.py diff --git a/doc/source/examples/npintensity.rst b/doc/source/examples/npintensity.rst new file mode 100644 index 00000000..be8705eb --- /dev/null +++ b/doc/source/examples/npintensity.rst @@ -0,0 +1,7 @@ +.. _npintensity.py: + +======================== +npintensity.py +======================== + +.. literalinclude:: ../../../examples/npintensity.py diff --git a/doc/source/examples/npintensityII.rst b/doc/source/examples/npintensityII.rst new file mode 100644 index 00000000..0fb043ea --- /dev/null +++ b/doc/source/examples/npintensityII.rst @@ -0,0 +1,7 @@ +.. _npintensityII.py: + +======================== +npintensityII.py +======================== + +.. literalinclude:: ../../../examples/npintensityII.py diff --git a/doc/source/examples/nppdfcrystal.rst b/doc/source/examples/nppdfcrystal.rst new file mode 100644 index 00000000..38bd3523 --- /dev/null +++ b/doc/source/examples/nppdfcrystal.rst @@ -0,0 +1,7 @@ +.. _nppdfcrystal.py: + +======================== +nppdfcrystal.py +======================== + +.. literalinclude:: ../../../examples/nppdfcrystal.py diff --git a/doc/source/examples/nppdfobjcryst.rst b/doc/source/examples/nppdfobjcryst.rst new file mode 100644 index 00000000..c5ba169e --- /dev/null +++ b/doc/source/examples/nppdfobjcryst.rst @@ -0,0 +1,7 @@ +.. _nppdfobjcryst.py: + +======================== +nppdfobjcryst.py +======================== + +.. literalinclude:: ../../../examples/nppdfobjcryst.py diff --git a/doc/source/examples/nppdfsas.rst b/doc/source/examples/nppdfsas.rst new file mode 100644 index 00000000..26852a89 --- /dev/null +++ b/doc/source/examples/nppdfsas.rst @@ -0,0 +1,7 @@ +.. _nppdfsas.py: + +======================== +nppdfsas.py +======================== + +.. literalinclude:: ../../../examples/nppdfsas.py diff --git a/doc/source/examples/simplepdf.rst b/doc/source/examples/simplepdf.rst new file mode 100644 index 00000000..a926db37 --- /dev/null +++ b/doc/source/examples/simplepdf.rst @@ -0,0 +1,7 @@ +.. _simplepdf.py: + +======================== +simplepdf.py +======================== + +.. literalinclude:: ../../../examples/simplepdf.py diff --git a/doc/source/examples/simplepdftwophase.rst b/doc/source/examples/simplepdftwophase.rst new file mode 100644 index 00000000..8e61dec2 --- /dev/null +++ b/doc/source/examples/simplepdftwophase.rst @@ -0,0 +1,7 @@ +.. _simplepdftwophase.py: + +======================== +simplepdftwophase.py +======================== + +.. literalinclude:: ../../../examples/simplepdftwophase.py diff --git a/doc/source/examples/simplerecipe.rst b/doc/source/examples/simplerecipe.rst new file mode 100644 index 00000000..046b09cd --- /dev/null +++ b/doc/source/examples/simplerecipe.rst @@ -0,0 +1,7 @@ +.. _simplerecipe.py: + +======================== +simplerecipe.py +======================== + +.. literalinclude:: ../../../examples/simplerecipe.py diff --git a/doc/source/extending.rst b/doc/source/extending.rst new file mode 100644 index 00000000..5aa596eb --- /dev/null +++ b/doc/source/extending.rst @@ -0,0 +1,267 @@ +.. _developers-guide-extending: + +=================== +Extending SrFit +=================== + +The :ref:`developers-guide-examples` give an overview of how to +use SrFit and extend it with various custom-made objects. Many pieces of SrFit +that are not covered in the examples are discussed here. + +Plugging Other Objects into SrFit +------------------------------------- + +Much of the power of SrFit comes from being able to plug existing python codes +into the framework. For example, external forward calculators can be wrapped up +inside ``ProfileGenerators`` without modifying the calculator. This is +demonstrated in :ref:`developers-guide-examples`. Structure adapters defined in +the diffpy.srfit.structure module are also built around this principle. These +adapters are hierarchical ``ParameterSets`` (found in +``diffpy.srfit.fitbase.parameterset``) that encapsulate the different pieces of +a structure. For example, the ``DiffpyStructureParSet`` structure adapter in +``diffpy.srfit.structure.diffpyparset`` contains ``DiffpyLatticeParSet``, which +encapsulates the lattice data and one ``DiffpyAtomParSet`` per atom. These +each contain parameters for what they encapsulate, such as lattice parameters +or atom positions. + +Fundamentally, it is the adjustable parameters of a structure container, +forward calculator or other object that needs to be adapted so that SrFit can +manipulate the underlying data object. These adapted parameters can then be +organized into ``ParameterSets``, as in the case of a structure adapter. The +``ParameterAdapter`` class found in ``diffpy.srfit.fitbase.parameter`` is +designed for this purpose. ``ParameterAdapter`` is a ``Parameter`` that defers +to another object when setting or retrieving its value. + +.. currentmodule:: diffpy.srfit.fitbase.parameter +.. autoclass:: ParameterAdapter + + The `name` argument is used to give attribute access to the + ParameterAdapter instance when it is added to a ParameterSet or similar + object. The `obj` argument is the parameter-like object to be adapted. It + must provide some form of access to its data. If it provides a getter and + setter, these can be specified with the `getter` and `setter` arguments. + If the getter and setter require an attribute name, this is specified with + the `attr` argument. If the data can be retrieved as an attribute, then the + name of this attribute can be passed in the `attr` argument. + + +Here is a simple example of using ``ParameterAdapter`` to adapt a hypothetical +atom object called ``SimpleAtom`` that has attributes ``x``, ``y`` and ``z``. +:: + + class SimpleAtom(object): + """Simple class holding x, y and z coordinates of an atom.""" + + def __init__(self, x, y, z): + self.x = x + self.y = y + self.z = z + return + + # End class SimpleAtom + + class SimpleAtomParSet(ParameterSet): + """Class adapting the x, y and z attributes of SimpleAtom as Parameters.""" + + def __init__(self, atom, name): + ParameterSet.__init__(self, name) + # Store the atom, we might need it later + self.atom = atom + + # Create a ParameterAdapter for the x, y and z attributes of atom + xpar = ParameterAdapter("x", atom, attr = "x") + ypar = ParameterAdapter("y", atom, attr = "y") + zpar = ParameterAdapter("z", atom, attr = "z") + + # Add these to the parameter set + self.addParameter(xpar) + self.addParameter(ypar) + self.addParameter(zpar) + + return + + # End class SimpleAtomParSet + +The ``x``, ``y`` and ``z`` attributes (specified by the ``attr`` keyword +argument of ``ParameterAdapter``) of a ``SimpleAtom`` are wrapped as +``ParameterAdapter`` objects named `x`, `y`, and `z`. They are then added to +the ``SimpleAtomParSet`` using the ``addParameter`` method, which makes them +accessible as attributes. + +If SimpleAtom did not have an attribute named ``x``, but rather accessor +methods named ``getX`` and ``setX``, then the ``ParameterAdapter`` would be +used as:: + + xpar = ParameterAdapter("x", atom, getter = SimpleAtom.getX, + setter = SimpleAtom.setX) + +Note that the *unbound* methods are used. The names ``getter`` and ``setter`` +describe how the accessor attributes are used to access the value of the +parameter. When ``xpar.getValue()`` is called, it redirects to +``SimpleAtom.getX(atom)``. + +If instead ``SimpleAtom`` had methods called ``get`` and ``set`` that take as +the second argument the name of the attribute to retrieve or modify, then this +can be adapted as:: + + xpar = ParameterAdapter("x", atom, getter = SimpleAtom.get, + setter = SimpleAtom.set, attr = "x") + +Thus, when ``xpar.getValue()`` is called, it in turn calls +``SimpleAtom.get(atom, "x")``. ``xpar.setValue(value)`` calls +``SimpleAtom.set(atom, "x", value)``. + +If the attributes of an object cannot be accessed in one of these three ways, +then you must write external accessor methods that can be set as the getter and +setter of the ``ParameterAdapter``. For example, if the ``x``, ``y`` and ``z`` +values were held in a list called ``xyz``, then you would have to write the +functions ``getX`` and ``setX`` that would manipulate this list, and use these +functions as in the second example. + + +Extending Profile Parsers +-------------------------- + +The ``ProfileParser`` class is located in the ``diffpy.srfit.fitbase.parser`` +module. The purpose of this class is to read data and metadata from a file or +string and pass those data and metadata to a ``Profile`` instance. The +``Profile`` in turn will pass this information to a ``ProfileGenerator``. + +The simplest way to extend the ``ProfileParser`` is to derive a new class from +``ProfileParser`` and overload the ``parseString`` method. By default, the +``parseFile`` method can read an ASCII file and passes the loaded string to the +``parseString`` method. For non-ASCII data one should overload both of these +methods. An example of a customized ``ProfileParser`` is the ``PDFParser`` +class in the ``diffpy.srfit.pdf.pdfparser`` module. + +Here is a simple example demonstrating how to extract (x,y) data from a +two-column string. :: + + def parseString(self, datastring): + + xvals = [] + yvals = [] + dxvals = None + dyvals = None + + for line in datastring.splitlines(): + + sline = line.split() + x, y = map(float, sline) + xvals.append(x) + yvals.append(y) + + self._banks.append([xvals, yvals, dxvals, dyvals]) + return + +The ``self._banks.append`` line puts the data arrays into the ``_banks`` list. +This list is for collecting multiple data sets that may be present within a +single file. The ``dxvals`` and ``dyvals`` are the uncertainty values on the +``xvals`` and ``yvals``. In this simple example they are not present, and so +are set to None. + +In general, the data string may contain metadata. The ``ProfileParser`` has a +dictionary attribute named ``_meta``. The parser can put any information into +this dictionary. It is up to a ``ProfileGenerator`` that may use the parsed +data to define and retrieve usable metadata. + +If the data are not in a form that can be stored in a ``Profile`` then it is +the responsibility of the parser to convert this data to a usable form. + + +Extending Profiles +-------------------------- + +Even with the ability to customize ``ProfileParsers,`` it may be necessary to +create custom ``Profile`` objects for different types of data. This is useful +when adapting an external data container to the SrFit interface. For example, +the external container may need to be retained so it can be used within an +external program before or after interfacing with SrFit. An example of a +customized Profile is the ``SASProfile`` class in the +``diffpy.srfit.sas.sasprofile`` module: + +.. literalinclude:: ../../../src/diffpy/srfit/sas/sasprofile.py + :pyobject: SASProfile + +The ``__init__`` method sets the ``xobs``, ``yobs`` and ``dyobs`` attributes of +the ``SASProfile`` to the associated arrays within the ``_datainfo`` attribute. +The ``setObservedProfile`` method is overloaded to modify the ``_datainfo`` +arrays when their corresponding attributes are modified. This keeps the arrays +in sync. + + +Custom Restraints +---------------------------------------- + +Restraints in SrFit are one way to include known information about a system +into a fit recipe. When customizing SrFit for a specific purpose, one may want +to create restraints. One example of this is in the ``SrRealParSet`` base class +in ``diffpy.srfit.structure.srrealparset``. SrReal provides many real-space +structure utilities for compatible structures, such as a PDF calculator and a +bond-valence sum (BVS) calculator. The PDF calculator works very well as a +``ProfileGenerator`` (see the :ref:`developers-guide-examples`), but the BVS +calculator is better suited as a restraint. This makes it very easy to keep the +BVS constrained during a PDF fit or some other refinement. + +Creating a custom restraint is a two-step process. First, a class must be +derived from ``diffpy.srfit.fitbase.restraint.Restraint`` that can calculate +the restraint cost. This requires the ``penalty`` method to be overloaded. +This method has the following signature + +.. currentmodule:: diffpy.srfit.fitbase.restraint +.. automethod:: Restraint.penalty + +The `w` factor is optionally used to scale the restraint cost. Its purpose is +to keep the restraint cost comparable to the residual of a single data point. + +``BVSRestraint`` from ``diffpy.srfit.structure.bvsrestraint`` is a custom +``Restraint`` whose penalty is the root-mean-square deviation from the expected +and calculated BVS of a structure. + +.. literalinclude:: ../../../src/diffpy/srfit/structure/bvsrestraint.py + :pyobject: BVSRestraint + +Note that the penalty scaling is optional (selected by the `scaled` flag) and +uncertainty on the result (`sig`) may be applied. These two options are +recommended with any custom ``Restraint``. + +The second part of a custom restraint is to allow it to be created from a +restrainable object. A ``BVSRestraint`` is used to restrain a ``SrRealParSet``, +which is a ``ParameterSet`` wrapper base class for SrReal-compatible +structures. The restraint is applied with the ``restrainBVS`` method. + +.. literalinclude:: ../../../src/diffpy/srfit/structure/srrealparset.py + :pyobject: SrRealParSet.restrainBVS + +The purpose of the method is to create the custom ``Restraint`` object, +configure it and store it. Note that the optional `sig` and `scaled` flag are +passed as part of this method. Both ``_restraints`` and +``_updateConfiguration`` come from ``ParameterSet``, from which +``SrRealParSet`` is derived. The ``_restraints`` attribute is a set of +``Restraints`` on the object. The ``_updateConfiguration`` method makes any +object containing the ``SrRealParSet`` aware of the configuration change. This +gets propagated to the top-level ``FitRecipe``, if there is one. The restraint +object is returned by the method so that it may be later removed. + +For more examples of custom restraints can be found in the +``diffpy.srfit.structure.objcrystparset`` module. + + +Custom FitHooks +-------------------------- + +The ``FitHook`` class is used by a ``FitRecipe`` to report fit progress to a +user. ``FitHook`` can be found in the ``diffpy.srfit.fitbase.fithook`` module. +``FitHook`` can be customized to provide customized fit output, such as a live +plot of the output. The ``FitHook`` class has three methods that one can +overload. + +.. currentmodule:: diffpy.srfit.fitbase.fithook + +* .. automethod:: FitHook.reset +* .. automethod:: FitHook.precall +* .. automethod:: FitHook.postcall + +To use a custom ``FitHook``, assign an instance to a ``FitRecipe`` using the +``pushFitHook`` method. All ``FitHook`` instances held by a ``FitRecipe`` will +be used in sequence during a call to ``FitRecipe.residual``. diff --git a/doc/source/index.rst b/doc/source/index.rst new file mode 100644 index 00000000..69a7994b --- /dev/null +++ b/doc/source/index.rst @@ -0,0 +1,44 @@ +####### +|title| +####### + +.. |title| replace:: diffpy.srfit documentation + +diffpy.srfit - SrFit - Structure refinement from diffraction data. + +| Software version |release|. +| Last updated |today|. + +======= +Authors +======= + +diffpy.srfit is developed by Billinge Group +and its community contributors. + +For a detailed list of contributors see +https://github.com/diffpy/diffpy.srfit/graphs/contributors. + +============ +Installation +============ + +See the `README `_ +file included with the distribution. + +================= +Table of contents +================= +.. toctree:: + :titlesonly: + + license + release + Package API + +======= +Indices +======= + +* :ref:`genindex` +* :ref:`search` diff --git a/doc/source/license.rst b/doc/source/license.rst new file mode 100644 index 00000000..cfab61c2 --- /dev/null +++ b/doc/source/license.rst @@ -0,0 +1,39 @@ +:tocdepth: -1 + +.. index:: license + +License +####### + +OPEN SOURCE LICENSE AGREEMENT +============================= +BSD 3-Clause License + +Copyright (c) 2024, The Trustees of Columbia University in +the City of New York. +All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/doc/source/release.rst b/doc/source/release.rst new file mode 100644 index 00000000..27cd0cc9 --- /dev/null +++ b/doc/source/release.rst @@ -0,0 +1,5 @@ +:tocdepth: -1 + +.. index:: release notes + +.. include:: ../../CHANGELOG.rst diff --git a/news/TEMPLATE.rst b/news/TEMPLATE.rst new file mode 100644 index 00000000..790d30b1 --- /dev/null +++ b/news/TEMPLATE.rst @@ -0,0 +1,23 @@ +**Added:** + +* + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* diff --git a/requirements/README.txt b/requirements/README.txt new file mode 100644 index 00000000..dc34909d --- /dev/null +++ b/requirements/README.txt @@ -0,0 +1,11 @@ +# YOU MAY DELETE THIS FILE AFTER SETTING UP DEPENDENCIES! +# +# This directory is where you should place your project dependencies. +# "pip.txt" should contain all required packages not available on conda. +# All other files should contain only packages available to download from conda. +# build.txt should contain all packages required to build (not run) the project. +# run.txt should contain all packages (including optional packages) required for a user to run the program. +# test.txt should contain all packages required for the testing suite and to ensure all tests pass. +# docs.txt should contain all packages required for building the package documentation page. +# +# YOU MAY DELETE THIS FILE AFTER SETTING UP DEPENDENCIES! diff --git a/requirements/build.txt b/requirements/build.txt new file mode 100644 index 00000000..f72d870d --- /dev/null +++ b/requirements/build.txt @@ -0,0 +1,2 @@ +python +setuptools diff --git a/requirements/docs.txt b/requirements/docs.txt new file mode 100644 index 00000000..ab17b1c8 --- /dev/null +++ b/requirements/docs.txt @@ -0,0 +1,4 @@ +sphinx +sphinx_rtd_theme +doctr +m2r diff --git a/requirements/pip.txt b/requirements/pip.txt new file mode 100644 index 00000000..e69de29b diff --git a/requirements/run.txt b/requirements/run.txt new file mode 100644 index 00000000..e69de29b diff --git a/requirements/test.txt b/requirements/test.txt new file mode 100644 index 00000000..6f9ccf84 --- /dev/null +++ b/requirements/test.txt @@ -0,0 +1,5 @@ +flake8 +pytest +codecov +coverage +pytest-env diff --git a/src/diffpy/srfit/tests/conftest.py b/src/diffpy/srfit/tests/conftest.py new file mode 100644 index 00000000..e3b63139 --- /dev/null +++ b/src/diffpy/srfit/tests/conftest.py @@ -0,0 +1,19 @@ +import json +from pathlib import Path + +import pytest + + +@pytest.fixture +def user_filesystem(tmp_path): + base_dir = Path(tmp_path) + home_dir = base_dir / "home_dir" + home_dir.mkdir(parents=True, exist_ok=True) + cwd_dir = base_dir / "cwd_dir" + cwd_dir.mkdir(parents=True, exist_ok=True) + + home_config_data = {"username": "home_username", "email": "home@email.com"} + with open(home_dir / "diffpyconfig.json", "w") as f: + json.dump(home_config_data, f) + + yield tmp_path From 0c4dc0fc18413c9a42f87caaf474a4657725f3f0 Mon Sep 17 00:00:00 2001 From: Tieqiong Zhang Date: Tue, 2 Jul 2024 12:09:57 -0400 Subject: [PATCH 02/21] remove extra doc/manual/source --- .../api/diffpy.srfit.equation.literals.rst | 46 --- .../source/api/diffpy.srfit.equation.rst | 38 --- .../api/diffpy.srfit.equation.visitors.rst | 54 ---- .../source/api/diffpy.srfit.fitbase.rst | 142 --------- .../source/api/diffpy.srfit.interface.rst | 22 -- doc/manual/source/api/diffpy.srfit.pdf.rst | 62 ---- doc/manual/source/api/diffpy.srfit.rst | 38 --- doc/manual/source/api/diffpy.srfit.sas.rst | 54 ---- .../source/api/diffpy.srfit.structure.rst | 70 ----- doc/manual/source/api/diffpy.srfit.util.rst | 46 --- doc/manual/source/conf.py | 274 ------------------ doc/manual/source/examples.rst | 56 ---- doc/manual/source/examples/coreshellnp.rst | 7 - doc/manual/source/examples/crystalpdf.rst | 7 - doc/manual/source/examples/crystalpdfall.rst | 7 - .../source/examples/crystalpdfobjcryst.rst | 7 - .../source/examples/crystalpdftwodata.rst | 7 - .../source/examples/crystalpdftwophase.rst | 7 - doc/manual/source/examples/debyemodel.rst | 7 - doc/manual/source/examples/debyemodelII.rst | 7 - doc/manual/source/examples/ellipsoidsas.rst | 7 - .../source/examples/gaussiangenerator.rst | 7 - doc/manual/source/examples/gaussianrecipe.rst | 7 - doc/manual/source/examples/interface.rst | 7 - doc/manual/source/examples/npintensity.rst | 7 - doc/manual/source/examples/npintensityII.rst | 7 - doc/manual/source/examples/nppdfcrystal.rst | 7 - doc/manual/source/examples/nppdfobjcryst.rst | 7 - doc/manual/source/examples/nppdfsas.rst | 7 - doc/manual/source/examples/simplepdf.rst | 7 - .../source/examples/simplepdftwophase.rst | 7 - doc/manual/source/examples/simplerecipe.rst | 7 - doc/manual/source/extending.rst | 267 ----------------- doc/manual/source/index.rst | 84 ------ doc/manual/source/license.rst | 142 --------- doc/manual/source/release.rst | 3 - 36 files changed, 1538 deletions(-) delete mode 100644 doc/manual/source/api/diffpy.srfit.equation.literals.rst delete mode 100644 doc/manual/source/api/diffpy.srfit.equation.rst delete mode 100644 doc/manual/source/api/diffpy.srfit.equation.visitors.rst delete mode 100644 doc/manual/source/api/diffpy.srfit.fitbase.rst delete mode 100644 doc/manual/source/api/diffpy.srfit.interface.rst delete mode 100644 doc/manual/source/api/diffpy.srfit.pdf.rst delete mode 100644 doc/manual/source/api/diffpy.srfit.rst delete mode 100644 doc/manual/source/api/diffpy.srfit.sas.rst delete mode 100644 doc/manual/source/api/diffpy.srfit.structure.rst delete mode 100644 doc/manual/source/api/diffpy.srfit.util.rst delete mode 100644 doc/manual/source/conf.py delete mode 100644 doc/manual/source/examples.rst delete mode 100644 doc/manual/source/examples/coreshellnp.rst delete mode 100644 doc/manual/source/examples/crystalpdf.rst delete mode 100644 doc/manual/source/examples/crystalpdfall.rst delete mode 100644 doc/manual/source/examples/crystalpdfobjcryst.rst delete mode 100644 doc/manual/source/examples/crystalpdftwodata.rst delete mode 100644 doc/manual/source/examples/crystalpdftwophase.rst delete mode 100644 doc/manual/source/examples/debyemodel.rst delete mode 100644 doc/manual/source/examples/debyemodelII.rst delete mode 100644 doc/manual/source/examples/ellipsoidsas.rst delete mode 100644 doc/manual/source/examples/gaussiangenerator.rst delete mode 100644 doc/manual/source/examples/gaussianrecipe.rst delete mode 100644 doc/manual/source/examples/interface.rst delete mode 100644 doc/manual/source/examples/npintensity.rst delete mode 100644 doc/manual/source/examples/npintensityII.rst delete mode 100644 doc/manual/source/examples/nppdfcrystal.rst delete mode 100644 doc/manual/source/examples/nppdfobjcryst.rst delete mode 100644 doc/manual/source/examples/nppdfsas.rst delete mode 100644 doc/manual/source/examples/simplepdf.rst delete mode 100644 doc/manual/source/examples/simplepdftwophase.rst delete mode 100644 doc/manual/source/examples/simplerecipe.rst delete mode 100644 doc/manual/source/extending.rst delete mode 100644 doc/manual/source/index.rst delete mode 100644 doc/manual/source/license.rst delete mode 100644 doc/manual/source/release.rst diff --git a/doc/manual/source/api/diffpy.srfit.equation.literals.rst b/doc/manual/source/api/diffpy.srfit.equation.literals.rst deleted file mode 100644 index 35b905b1..00000000 --- a/doc/manual/source/api/diffpy.srfit.equation.literals.rst +++ /dev/null @@ -1,46 +0,0 @@ -diffpy.srfit.equation.literals package -====================================== - -Submodules ----------- - -diffpy.srfit.equation.literals.abcs module ------------------------------------------- - -.. automodule:: diffpy.srfit.equation.literals.abcs - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.equation.literals.argument module ----------------------------------------------- - -.. automodule:: diffpy.srfit.equation.literals.argument - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.equation.literals.literal module ---------------------------------------------- - -.. automodule:: diffpy.srfit.equation.literals.literal - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.equation.literals.operators module ------------------------------------------------ - -.. automodule:: diffpy.srfit.equation.literals.operators - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: diffpy.srfit.equation.literals - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/manual/source/api/diffpy.srfit.equation.rst b/doc/manual/source/api/diffpy.srfit.equation.rst deleted file mode 100644 index f5642da1..00000000 --- a/doc/manual/source/api/diffpy.srfit.equation.rst +++ /dev/null @@ -1,38 +0,0 @@ -diffpy.srfit.equation package -============================= - -Subpackages ------------ - -.. toctree:: - - diffpy.srfit.equation.literals - diffpy.srfit.equation.visitors - -Submodules ----------- - -diffpy.srfit.equation.builder module ------------------------------------- - -.. automodule:: diffpy.srfit.equation.builder - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.equation.equationmod module ----------------------------------------- - -.. automodule:: diffpy.srfit.equation.equationmod - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: diffpy.srfit.equation - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/manual/source/api/diffpy.srfit.equation.visitors.rst b/doc/manual/source/api/diffpy.srfit.equation.visitors.rst deleted file mode 100644 index de17f93d..00000000 --- a/doc/manual/source/api/diffpy.srfit.equation.visitors.rst +++ /dev/null @@ -1,54 +0,0 @@ -diffpy.srfit.equation.visitors package -====================================== - -Submodules ----------- - -diffpy.srfit.equation.visitors.argfinder module ------------------------------------------------ - -.. automodule:: diffpy.srfit.equation.visitors.argfinder - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.equation.visitors.printer module ---------------------------------------------- - -.. automodule:: diffpy.srfit.equation.visitors.printer - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.equation.visitors.swapper module ---------------------------------------------- - -.. automodule:: diffpy.srfit.equation.visitors.swapper - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.equation.visitors.validator module ------------------------------------------------ - -.. automodule:: diffpy.srfit.equation.visitors.validator - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.equation.visitors.visitor module ---------------------------------------------- - -.. automodule:: diffpy.srfit.equation.visitors.visitor - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: diffpy.srfit.equation.visitors - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/manual/source/api/diffpy.srfit.fitbase.rst b/doc/manual/source/api/diffpy.srfit.fitbase.rst deleted file mode 100644 index 44093442..00000000 --- a/doc/manual/source/api/diffpy.srfit.fitbase.rst +++ /dev/null @@ -1,142 +0,0 @@ -diffpy.srfit.fitbase package -============================ - -Submodules ----------- - -diffpy.srfit.fitbase.calculator module --------------------------------------- - -.. automodule:: diffpy.srfit.fitbase.calculator - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.fitbase.configurable module ----------------------------------------- - -.. automodule:: diffpy.srfit.fitbase.configurable - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.fitbase.constraint module --------------------------------------- - -.. automodule:: diffpy.srfit.fitbase.constraint - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.fitbase.fitcontribution module -------------------------------------------- - -.. automodule:: diffpy.srfit.fitbase.fitcontribution - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.fitbase.fithook module ------------------------------------ - -.. automodule:: diffpy.srfit.fitbase.fithook - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.fitbase.fitrecipe module -------------------------------------- - -.. automodule:: diffpy.srfit.fitbase.fitrecipe - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.fitbase.fitresults module --------------------------------------- - -.. automodule:: diffpy.srfit.fitbase.fitresults - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.fitbase.parameter module -------------------------------------- - -.. automodule:: diffpy.srfit.fitbase.parameter - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.fitbase.parameterset module ----------------------------------------- - -.. automodule:: diffpy.srfit.fitbase.parameterset - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.fitbase.profile module ------------------------------------ - -.. automodule:: diffpy.srfit.fitbase.profile - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.fitbase.profilegenerator module --------------------------------------------- - -.. automodule:: diffpy.srfit.fitbase.profilegenerator - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.fitbase.profileparser module ------------------------------------------ - -.. automodule:: diffpy.srfit.fitbase.profileparser - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.fitbase.recipeorganizer module -------------------------------------------- - -.. automodule:: diffpy.srfit.fitbase.recipeorganizer - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.fitbase.restraint module -------------------------------------- - -.. automodule:: diffpy.srfit.fitbase.restraint - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.fitbase.simplerecipe module ----------------------------------------- - -.. automodule:: diffpy.srfit.fitbase.simplerecipe - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.fitbase.validatable module ---------------------------------------- - -.. automodule:: diffpy.srfit.fitbase.validatable - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: diffpy.srfit.fitbase - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/manual/source/api/diffpy.srfit.interface.rst b/doc/manual/source/api/diffpy.srfit.interface.rst deleted file mode 100644 index 4b6296a8..00000000 --- a/doc/manual/source/api/diffpy.srfit.interface.rst +++ /dev/null @@ -1,22 +0,0 @@ -diffpy.srfit.interface package -============================== - -Submodules ----------- - -diffpy.srfit.interface.interface module ---------------------------------------- - -.. automodule:: diffpy.srfit.interface.interface - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: diffpy.srfit.interface - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/manual/source/api/diffpy.srfit.pdf.rst b/doc/manual/source/api/diffpy.srfit.pdf.rst deleted file mode 100644 index a336a375..00000000 --- a/doc/manual/source/api/diffpy.srfit.pdf.rst +++ /dev/null @@ -1,62 +0,0 @@ -diffpy.srfit.pdf package -======================== - -Submodules ----------- - -diffpy.srfit.pdf.basepdfgenerator module ----------------------------------------- - -.. automodule:: diffpy.srfit.pdf.basepdfgenerator - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.pdf.characteristicfunctions module ------------------------------------------------ - -.. automodule:: diffpy.srfit.pdf.characteristicfunctions - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.pdf.debyepdfgenerator module ------------------------------------------ - -.. automodule:: diffpy.srfit.pdf.debyepdfgenerator - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.pdf.pdfcontribution module ---------------------------------------- - -.. automodule:: diffpy.srfit.pdf.pdfcontribution - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.pdf.pdfgenerator module ------------------------------------- - -.. automodule:: diffpy.srfit.pdf.pdfgenerator - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.pdf.pdfparser module ---------------------------------- - -.. automodule:: diffpy.srfit.pdf.pdfparser - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: diffpy.srfit.pdf - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/manual/source/api/diffpy.srfit.rst b/doc/manual/source/api/diffpy.srfit.rst deleted file mode 100644 index bbe6224d..00000000 --- a/doc/manual/source/api/diffpy.srfit.rst +++ /dev/null @@ -1,38 +0,0 @@ -:tocdepth: 2 - -diffpy.srfit package -==================== - -Subpackages ------------ - -.. toctree:: - :maxdepth: 2 - - diffpy.srfit.equation - diffpy.srfit.fitbase - diffpy.srfit.interface - diffpy.srfit.pdf - diffpy.srfit.sas - diffpy.srfit.structure - diffpy.srfit.util - -Submodules ----------- - -diffpy.srfit.version module ---------------------------- - -.. automodule:: diffpy.srfit.version - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: diffpy.srfit - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/manual/source/api/diffpy.srfit.sas.rst b/doc/manual/source/api/diffpy.srfit.sas.rst deleted file mode 100644 index 40f24b3d..00000000 --- a/doc/manual/source/api/diffpy.srfit.sas.rst +++ /dev/null @@ -1,54 +0,0 @@ -diffpy.srfit.sas package -======================== - -Submodules ----------- - -diffpy.srfit.sas.prcalculator module ------------------------------------- - -.. automodule:: diffpy.srfit.sas.prcalculator - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.sas.sasgenerator module ------------------------------------- - -.. automodule:: diffpy.srfit.sas.sasgenerator - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.sas.sasparameter module ------------------------------------- - -.. automodule:: diffpy.srfit.sas.sasparameter - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.sas.sasparser module ---------------------------------- - -.. automodule:: diffpy.srfit.sas.sasparser - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.sas.sasprofile module ----------------------------------- - -.. automodule:: diffpy.srfit.sas.sasprofile - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: diffpy.srfit.sas - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/manual/source/api/diffpy.srfit.structure.rst b/doc/manual/source/api/diffpy.srfit.structure.rst deleted file mode 100644 index 1bb5dd22..00000000 --- a/doc/manual/source/api/diffpy.srfit.structure.rst +++ /dev/null @@ -1,70 +0,0 @@ -diffpy.srfit.structure package -============================== - -Submodules ----------- - -diffpy.srfit.structure.basestructureparset module -------------------------------------------------- - -.. automodule:: diffpy.srfit.structure.basestructureparset - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.structure.bvsrestraint module ------------------------------------------- - -.. automodule:: diffpy.srfit.structure.bvsrestraint - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.structure.cctbxparset module ------------------------------------------ - -.. automodule:: diffpy.srfit.structure.cctbxparset - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.structure.diffpyparset module ------------------------------------------- - -.. automodule:: diffpy.srfit.structure.diffpyparset - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.structure.objcrystparset module --------------------------------------------- - -.. automodule:: diffpy.srfit.structure.objcrystparset - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.structure.sgconstraints module -------------------------------------------- - -.. automodule:: diffpy.srfit.structure.sgconstraints - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.structure.srrealparset module ------------------------------------------- - -.. automodule:: diffpy.srfit.structure.srrealparset - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: diffpy.srfit.structure - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/manual/source/api/diffpy.srfit.util.rst b/doc/manual/source/api/diffpy.srfit.util.rst deleted file mode 100644 index 64541ce6..00000000 --- a/doc/manual/source/api/diffpy.srfit.util.rst +++ /dev/null @@ -1,46 +0,0 @@ -diffpy.srfit.util package -========================= - -Submodules ----------- - -diffpy.srfit.util.inpututils module ------------------------------------ - -.. automodule:: diffpy.srfit.util.inpututils - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.util.nameutils module ----------------------------------- - -.. automodule:: diffpy.srfit.util.nameutils - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.util.observable module ------------------------------------ - -.. automodule:: diffpy.srfit.util.observable - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.util.tagmanager module ------------------------------------ - -.. automodule:: diffpy.srfit.util.tagmanager - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: diffpy.srfit.util - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/manual/source/conf.py b/doc/manual/source/conf.py deleted file mode 100644 index 53398e50..00000000 --- a/doc/manual/source/conf.py +++ /dev/null @@ -1,274 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# diffpy.srfit documentation build configuration file, created by -# sphinx-quickstart on Fri Dec 6 18:09:01 2013. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, os -import time - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# sys.path.insert(0, os.path.abspath('.')) -# sys.path.insert(0, os.path.abspath('../../..')) - -# abbreviations -ab_authors = u'Christopher L. Farrow, Pavol Juhás, Simon J.L. Billinge group' - -# -- General configuration ----------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.napoleon', - 'sphinx.ext.intersphinx', - 'm2r', -] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# -source_suffix = ['.rst', '.md'] - -# The encoding of source files. -# source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'diffpy.srfit' -copyright = u'%Y, Brookhaven National Laboratory' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -sys.path.insert(0, os.path.abspath('../../..')) -from setup import versiondata -fullversion = versiondata.get('DEFAULT', 'version') -# The short X.Y version. -version = ''.join(fullversion.split('.post')[:1]) -# The full version, including alpha/beta/rc tags. -release = fullversion - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# today = '' -today_seconds = versiondata.getint('DEFAULT', 'timestamp') -today = time.strftime('%B %d, %Y', time.localtime(today_seconds)) -year = today.split()[-1] -# Else, today_fmt is used as the format for a strftime call. -# today_fmt = '%B %d, %Y' -# substitute YEAR in the copyright string -copyright = copyright.replace('%Y', year) - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = [] - -# The reST default role (used for this markup: `text`) to use for all documents. -# default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -# add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -# add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -# show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -modindex_common_prefix = ['diffpy.srfit.'] - -# Display all warnings for missing links. -nitpicky = True - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'sphinx_py3doc_enhanced_theme' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -html_theme_options = { - 'collapsiblesidebar' : 'true', - 'navigation_with_keys' : 'true', -} - -# Add any paths that contain custom themes here, relative to this directory. -# html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -# html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -# html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -# html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = {} - -# If false, no module index is generated. -# html_domain_indices = True - -# If false, no index is generated. -# html_use_index = True - -# If true, the index is split into individual pages for each letter. -html_split_index = True - -# If true, links to the reST sources are added to the pages. -# html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'srfitdoc' - - -# -- Options for LaTeX output -------------------------------------------------- - -latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -# 'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -# 'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -# 'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ('index', 'srfit_manual.tex', u'diffpy.srfit documentation', - ab_authors, 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -# latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# latex_use_parts = False - -# If true, show page references after internal links. -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# latex_show_urls = False - -# Documents to append as an appendix to all manuals. -# latex_appendices = [] - -# If false, no module index is generated. -# latex_domain_indices = True - - -# -- Options for manual page output -------------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'diffpy.srfit', u'diffpy.srfit documentation', - ab_authors, 1) -] - -# If true, show URL addresses after external links. -# man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------------ - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ('index', 'diffpy.srfit', u'diffpy.srfit documentation', - ab_authors, 'diffpy.srfit', 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -# texinfo_appendices = [] - -# If false, no module index is generated. -# texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -# texinfo_show_urls = 'footnote' - - -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = { - 'numpy': ('https://docs.scipy.org/doc/numpy', None), - 'python' : ('https://docs.python.org/3.7', None), -} diff --git a/doc/manual/source/examples.rst b/doc/manual/source/examples.rst deleted file mode 100644 index 2403d1b8..00000000 --- a/doc/manual/source/examples.rst +++ /dev/null @@ -1,56 +0,0 @@ -.. _developers-guide-examples: - -=================== -Examples -=================== - -.. include:: ../../examples/README - -.. This creates the links from the filenames within README to pages. -.. _gaussianrecipe.py: examples/gaussianrecipe.html -.. _debyemodel.py: examples/debyemodel.html -.. _debyemodelII.py: examples/debyemodelII.html -.. _gaussiangenerator.py: examples/gaussiangenerator.html -.. _npintensity.py: examples/npintensity.html -.. _npintensityII.py: examples/npintensityII.html -.. _nppdfobjcryst.py: examples/nppdfobjcryst.html -.. _crystalpdf.py: examples/crystalpdf.html -.. _simplepdf.py: examples/simplepdf.html -.. _crystalpdfobjcryst.py: examples/crystalpdfobjcryst.html -.. _crystalpdftwophase.py: examples/crystalpdftwophase.html -.. _simplepdftwophase.py: examples/simplepdftwophase.html -.. _crystalpdftwodata.py: examples/crystalpdftwodata.html -.. _crystalpdfall.py: examples/crystalpdfall.html -.. _nppdfcrystal.py: examples/nppdfcrystal.html -.. _coreshellnp.py: examples/coreshellnp.html -.. _ellipsoidsas.py: examples/ellipsoidsas.html -.. _nppdfsas.py: examples/nppdfsas.html -.. _interface.py: examples/interface.html -.. _simplerecipe.py: examples/simplerecipe.html - - -Files ----------- - -.. toctree:: - - examples/gaussianrecipe.rst - examples/debyemodel.rst - examples/debyemodelII.rst - examples/gaussiangenerator.rst - examples/npintensity.rst - examples/npintensityII.rst - examples/nppdfobjcryst.rst - examples/crystalpdf.rst - examples/simplepdf.rst - examples/crystalpdfobjcryst.rst - examples/crystalpdftwophase.rst - examples/simplepdftwophase.rst - examples/crystalpdftwodata.rst - examples/crystalpdfall.rst - examples/nppdfcrystal.rst - examples/coreshellnp.rst - examples/ellipsoidsas.rst - examples/nppdfsas.rst - examples/interface.rst - examples/simplerecipe.rst diff --git a/doc/manual/source/examples/coreshellnp.rst b/doc/manual/source/examples/coreshellnp.rst deleted file mode 100644 index d8a84e0f..00000000 --- a/doc/manual/source/examples/coreshellnp.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _coreshellnp.py: - -======================== -coreshellnp.py -======================== - -.. literalinclude:: ../../../examples/coreshellnp.py diff --git a/doc/manual/source/examples/crystalpdf.rst b/doc/manual/source/examples/crystalpdf.rst deleted file mode 100644 index 51ef5185..00000000 --- a/doc/manual/source/examples/crystalpdf.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _crystalpdf.py: - -======================== -crystalpdf.py -======================== - -.. literalinclude:: ../../../examples/crystalpdf.py diff --git a/doc/manual/source/examples/crystalpdfall.rst b/doc/manual/source/examples/crystalpdfall.rst deleted file mode 100644 index b2f74fb8..00000000 --- a/doc/manual/source/examples/crystalpdfall.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _crystalpdfall.py: - -======================== -crystalpdfall.py -======================== - -.. literalinclude:: ../../../examples/crystalpdfall.py diff --git a/doc/manual/source/examples/crystalpdfobjcryst.rst b/doc/manual/source/examples/crystalpdfobjcryst.rst deleted file mode 100644 index 4542b65a..00000000 --- a/doc/manual/source/examples/crystalpdfobjcryst.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _crystalpdfobjcryst.py: - -======================== -crystalpdfobjcryst.py -======================== - -.. literalinclude:: ../../../examples/crystalpdfobjcryst.py diff --git a/doc/manual/source/examples/crystalpdftwodata.rst b/doc/manual/source/examples/crystalpdftwodata.rst deleted file mode 100644 index 9b42e45f..00000000 --- a/doc/manual/source/examples/crystalpdftwodata.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _crystalpdftwodata.py: - -======================== -crystalpdftwodata.py -======================== - -.. literalinclude:: ../../../examples/crystalpdftwodata.py diff --git a/doc/manual/source/examples/crystalpdftwophase.rst b/doc/manual/source/examples/crystalpdftwophase.rst deleted file mode 100644 index eb2cf18b..00000000 --- a/doc/manual/source/examples/crystalpdftwophase.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _crystalpdftwophase.py: - -======================== -crystalpdftwophase.py -======================== - -.. literalinclude:: ../../../examples/crystalpdftwophase.py diff --git a/doc/manual/source/examples/debyemodel.rst b/doc/manual/source/examples/debyemodel.rst deleted file mode 100644 index 436d20ca..00000000 --- a/doc/manual/source/examples/debyemodel.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _debyemodel.py: - -======================== -debyemodel.py -======================== - -.. literalinclude:: ../../../examples/debyemodel.py diff --git a/doc/manual/source/examples/debyemodelII.rst b/doc/manual/source/examples/debyemodelII.rst deleted file mode 100644 index d44cc60d..00000000 --- a/doc/manual/source/examples/debyemodelII.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _debyemodelII.py: - -======================== -debyemodelII.py -======================== - -.. literalinclude:: ../../../examples/debyemodelII.py diff --git a/doc/manual/source/examples/ellipsoidsas.rst b/doc/manual/source/examples/ellipsoidsas.rst deleted file mode 100644 index 132b2ee7..00000000 --- a/doc/manual/source/examples/ellipsoidsas.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _ellipsoidsas.py: - -======================== -ellipsoidsas.py -======================== - -.. literalinclude:: ../../../examples/ellipsoidsas.py diff --git a/doc/manual/source/examples/gaussiangenerator.rst b/doc/manual/source/examples/gaussiangenerator.rst deleted file mode 100644 index eb101bb9..00000000 --- a/doc/manual/source/examples/gaussiangenerator.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _gaussiangenerator.py: - -======================== -gaussiangenerator.py -======================== - -.. literalinclude:: ../../../examples/gaussiangenerator.py diff --git a/doc/manual/source/examples/gaussianrecipe.rst b/doc/manual/source/examples/gaussianrecipe.rst deleted file mode 100644 index 73f94eac..00000000 --- a/doc/manual/source/examples/gaussianrecipe.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _gaussianrecipe.py: - -======================== -gaussianrecipe.py -======================== - -.. literalinclude:: ../../../examples/gaussianrecipe.py diff --git a/doc/manual/source/examples/interface.rst b/doc/manual/source/examples/interface.rst deleted file mode 100644 index 41e706a8..00000000 --- a/doc/manual/source/examples/interface.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _interface.py: - -======================== -interface.py -======================== - -.. literalinclude:: ../../../examples/interface.py diff --git a/doc/manual/source/examples/npintensity.rst b/doc/manual/source/examples/npintensity.rst deleted file mode 100644 index be8705eb..00000000 --- a/doc/manual/source/examples/npintensity.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _npintensity.py: - -======================== -npintensity.py -======================== - -.. literalinclude:: ../../../examples/npintensity.py diff --git a/doc/manual/source/examples/npintensityII.rst b/doc/manual/source/examples/npintensityII.rst deleted file mode 100644 index 0fb043ea..00000000 --- a/doc/manual/source/examples/npintensityII.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _npintensityII.py: - -======================== -npintensityII.py -======================== - -.. literalinclude:: ../../../examples/npintensityII.py diff --git a/doc/manual/source/examples/nppdfcrystal.rst b/doc/manual/source/examples/nppdfcrystal.rst deleted file mode 100644 index 38bd3523..00000000 --- a/doc/manual/source/examples/nppdfcrystal.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _nppdfcrystal.py: - -======================== -nppdfcrystal.py -======================== - -.. literalinclude:: ../../../examples/nppdfcrystal.py diff --git a/doc/manual/source/examples/nppdfobjcryst.rst b/doc/manual/source/examples/nppdfobjcryst.rst deleted file mode 100644 index c5ba169e..00000000 --- a/doc/manual/source/examples/nppdfobjcryst.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _nppdfobjcryst.py: - -======================== -nppdfobjcryst.py -======================== - -.. literalinclude:: ../../../examples/nppdfobjcryst.py diff --git a/doc/manual/source/examples/nppdfsas.rst b/doc/manual/source/examples/nppdfsas.rst deleted file mode 100644 index 26852a89..00000000 --- a/doc/manual/source/examples/nppdfsas.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _nppdfsas.py: - -======================== -nppdfsas.py -======================== - -.. literalinclude:: ../../../examples/nppdfsas.py diff --git a/doc/manual/source/examples/simplepdf.rst b/doc/manual/source/examples/simplepdf.rst deleted file mode 100644 index a926db37..00000000 --- a/doc/manual/source/examples/simplepdf.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _simplepdf.py: - -======================== -simplepdf.py -======================== - -.. literalinclude:: ../../../examples/simplepdf.py diff --git a/doc/manual/source/examples/simplepdftwophase.rst b/doc/manual/source/examples/simplepdftwophase.rst deleted file mode 100644 index 8e61dec2..00000000 --- a/doc/manual/source/examples/simplepdftwophase.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _simplepdftwophase.py: - -======================== -simplepdftwophase.py -======================== - -.. literalinclude:: ../../../examples/simplepdftwophase.py diff --git a/doc/manual/source/examples/simplerecipe.rst b/doc/manual/source/examples/simplerecipe.rst deleted file mode 100644 index 046b09cd..00000000 --- a/doc/manual/source/examples/simplerecipe.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _simplerecipe.py: - -======================== -simplerecipe.py -======================== - -.. literalinclude:: ../../../examples/simplerecipe.py diff --git a/doc/manual/source/extending.rst b/doc/manual/source/extending.rst deleted file mode 100644 index 5aa596eb..00000000 --- a/doc/manual/source/extending.rst +++ /dev/null @@ -1,267 +0,0 @@ -.. _developers-guide-extending: - -=================== -Extending SrFit -=================== - -The :ref:`developers-guide-examples` give an overview of how to -use SrFit and extend it with various custom-made objects. Many pieces of SrFit -that are not covered in the examples are discussed here. - -Plugging Other Objects into SrFit -------------------------------------- - -Much of the power of SrFit comes from being able to plug existing python codes -into the framework. For example, external forward calculators can be wrapped up -inside ``ProfileGenerators`` without modifying the calculator. This is -demonstrated in :ref:`developers-guide-examples`. Structure adapters defined in -the diffpy.srfit.structure module are also built around this principle. These -adapters are hierarchical ``ParameterSets`` (found in -``diffpy.srfit.fitbase.parameterset``) that encapsulate the different pieces of -a structure. For example, the ``DiffpyStructureParSet`` structure adapter in -``diffpy.srfit.structure.diffpyparset`` contains ``DiffpyLatticeParSet``, which -encapsulates the lattice data and one ``DiffpyAtomParSet`` per atom. These -each contain parameters for what they encapsulate, such as lattice parameters -or atom positions. - -Fundamentally, it is the adjustable parameters of a structure container, -forward calculator or other object that needs to be adapted so that SrFit can -manipulate the underlying data object. These adapted parameters can then be -organized into ``ParameterSets``, as in the case of a structure adapter. The -``ParameterAdapter`` class found in ``diffpy.srfit.fitbase.parameter`` is -designed for this purpose. ``ParameterAdapter`` is a ``Parameter`` that defers -to another object when setting or retrieving its value. - -.. currentmodule:: diffpy.srfit.fitbase.parameter -.. autoclass:: ParameterAdapter - - The `name` argument is used to give attribute access to the - ParameterAdapter instance when it is added to a ParameterSet or similar - object. The `obj` argument is the parameter-like object to be adapted. It - must provide some form of access to its data. If it provides a getter and - setter, these can be specified with the `getter` and `setter` arguments. - If the getter and setter require an attribute name, this is specified with - the `attr` argument. If the data can be retrieved as an attribute, then the - name of this attribute can be passed in the `attr` argument. - - -Here is a simple example of using ``ParameterAdapter`` to adapt a hypothetical -atom object called ``SimpleAtom`` that has attributes ``x``, ``y`` and ``z``. -:: - - class SimpleAtom(object): - """Simple class holding x, y and z coordinates of an atom.""" - - def __init__(self, x, y, z): - self.x = x - self.y = y - self.z = z - return - - # End class SimpleAtom - - class SimpleAtomParSet(ParameterSet): - """Class adapting the x, y and z attributes of SimpleAtom as Parameters.""" - - def __init__(self, atom, name): - ParameterSet.__init__(self, name) - # Store the atom, we might need it later - self.atom = atom - - # Create a ParameterAdapter for the x, y and z attributes of atom - xpar = ParameterAdapter("x", atom, attr = "x") - ypar = ParameterAdapter("y", atom, attr = "y") - zpar = ParameterAdapter("z", atom, attr = "z") - - # Add these to the parameter set - self.addParameter(xpar) - self.addParameter(ypar) - self.addParameter(zpar) - - return - - # End class SimpleAtomParSet - -The ``x``, ``y`` and ``z`` attributes (specified by the ``attr`` keyword -argument of ``ParameterAdapter``) of a ``SimpleAtom`` are wrapped as -``ParameterAdapter`` objects named `x`, `y`, and `z`. They are then added to -the ``SimpleAtomParSet`` using the ``addParameter`` method, which makes them -accessible as attributes. - -If SimpleAtom did not have an attribute named ``x``, but rather accessor -methods named ``getX`` and ``setX``, then the ``ParameterAdapter`` would be -used as:: - - xpar = ParameterAdapter("x", atom, getter = SimpleAtom.getX, - setter = SimpleAtom.setX) - -Note that the *unbound* methods are used. The names ``getter`` and ``setter`` -describe how the accessor attributes are used to access the value of the -parameter. When ``xpar.getValue()`` is called, it redirects to -``SimpleAtom.getX(atom)``. - -If instead ``SimpleAtom`` had methods called ``get`` and ``set`` that take as -the second argument the name of the attribute to retrieve or modify, then this -can be adapted as:: - - xpar = ParameterAdapter("x", atom, getter = SimpleAtom.get, - setter = SimpleAtom.set, attr = "x") - -Thus, when ``xpar.getValue()`` is called, it in turn calls -``SimpleAtom.get(atom, "x")``. ``xpar.setValue(value)`` calls -``SimpleAtom.set(atom, "x", value)``. - -If the attributes of an object cannot be accessed in one of these three ways, -then you must write external accessor methods that can be set as the getter and -setter of the ``ParameterAdapter``. For example, if the ``x``, ``y`` and ``z`` -values were held in a list called ``xyz``, then you would have to write the -functions ``getX`` and ``setX`` that would manipulate this list, and use these -functions as in the second example. - - -Extending Profile Parsers --------------------------- - -The ``ProfileParser`` class is located in the ``diffpy.srfit.fitbase.parser`` -module. The purpose of this class is to read data and metadata from a file or -string and pass those data and metadata to a ``Profile`` instance. The -``Profile`` in turn will pass this information to a ``ProfileGenerator``. - -The simplest way to extend the ``ProfileParser`` is to derive a new class from -``ProfileParser`` and overload the ``parseString`` method. By default, the -``parseFile`` method can read an ASCII file and passes the loaded string to the -``parseString`` method. For non-ASCII data one should overload both of these -methods. An example of a customized ``ProfileParser`` is the ``PDFParser`` -class in the ``diffpy.srfit.pdf.pdfparser`` module. - -Here is a simple example demonstrating how to extract (x,y) data from a -two-column string. :: - - def parseString(self, datastring): - - xvals = [] - yvals = [] - dxvals = None - dyvals = None - - for line in datastring.splitlines(): - - sline = line.split() - x, y = map(float, sline) - xvals.append(x) - yvals.append(y) - - self._banks.append([xvals, yvals, dxvals, dyvals]) - return - -The ``self._banks.append`` line puts the data arrays into the ``_banks`` list. -This list is for collecting multiple data sets that may be present within a -single file. The ``dxvals`` and ``dyvals`` are the uncertainty values on the -``xvals`` and ``yvals``. In this simple example they are not present, and so -are set to None. - -In general, the data string may contain metadata. The ``ProfileParser`` has a -dictionary attribute named ``_meta``. The parser can put any information into -this dictionary. It is up to a ``ProfileGenerator`` that may use the parsed -data to define and retrieve usable metadata. - -If the data are not in a form that can be stored in a ``Profile`` then it is -the responsibility of the parser to convert this data to a usable form. - - -Extending Profiles --------------------------- - -Even with the ability to customize ``ProfileParsers,`` it may be necessary to -create custom ``Profile`` objects for different types of data. This is useful -when adapting an external data container to the SrFit interface. For example, -the external container may need to be retained so it can be used within an -external program before or after interfacing with SrFit. An example of a -customized Profile is the ``SASProfile`` class in the -``diffpy.srfit.sas.sasprofile`` module: - -.. literalinclude:: ../../../src/diffpy/srfit/sas/sasprofile.py - :pyobject: SASProfile - -The ``__init__`` method sets the ``xobs``, ``yobs`` and ``dyobs`` attributes of -the ``SASProfile`` to the associated arrays within the ``_datainfo`` attribute. -The ``setObservedProfile`` method is overloaded to modify the ``_datainfo`` -arrays when their corresponding attributes are modified. This keeps the arrays -in sync. - - -Custom Restraints ----------------------------------------- - -Restraints in SrFit are one way to include known information about a system -into a fit recipe. When customizing SrFit for a specific purpose, one may want -to create restraints. One example of this is in the ``SrRealParSet`` base class -in ``diffpy.srfit.structure.srrealparset``. SrReal provides many real-space -structure utilities for compatible structures, such as a PDF calculator and a -bond-valence sum (BVS) calculator. The PDF calculator works very well as a -``ProfileGenerator`` (see the :ref:`developers-guide-examples`), but the BVS -calculator is better suited as a restraint. This makes it very easy to keep the -BVS constrained during a PDF fit or some other refinement. - -Creating a custom restraint is a two-step process. First, a class must be -derived from ``diffpy.srfit.fitbase.restraint.Restraint`` that can calculate -the restraint cost. This requires the ``penalty`` method to be overloaded. -This method has the following signature - -.. currentmodule:: diffpy.srfit.fitbase.restraint -.. automethod:: Restraint.penalty - -The `w` factor is optionally used to scale the restraint cost. Its purpose is -to keep the restraint cost comparable to the residual of a single data point. - -``BVSRestraint`` from ``diffpy.srfit.structure.bvsrestraint`` is a custom -``Restraint`` whose penalty is the root-mean-square deviation from the expected -and calculated BVS of a structure. - -.. literalinclude:: ../../../src/diffpy/srfit/structure/bvsrestraint.py - :pyobject: BVSRestraint - -Note that the penalty scaling is optional (selected by the `scaled` flag) and -uncertainty on the result (`sig`) may be applied. These two options are -recommended with any custom ``Restraint``. - -The second part of a custom restraint is to allow it to be created from a -restrainable object. A ``BVSRestraint`` is used to restrain a ``SrRealParSet``, -which is a ``ParameterSet`` wrapper base class for SrReal-compatible -structures. The restraint is applied with the ``restrainBVS`` method. - -.. literalinclude:: ../../../src/diffpy/srfit/structure/srrealparset.py - :pyobject: SrRealParSet.restrainBVS - -The purpose of the method is to create the custom ``Restraint`` object, -configure it and store it. Note that the optional `sig` and `scaled` flag are -passed as part of this method. Both ``_restraints`` and -``_updateConfiguration`` come from ``ParameterSet``, from which -``SrRealParSet`` is derived. The ``_restraints`` attribute is a set of -``Restraints`` on the object. The ``_updateConfiguration`` method makes any -object containing the ``SrRealParSet`` aware of the configuration change. This -gets propagated to the top-level ``FitRecipe``, if there is one. The restraint -object is returned by the method so that it may be later removed. - -For more examples of custom restraints can be found in the -``diffpy.srfit.structure.objcrystparset`` module. - - -Custom FitHooks --------------------------- - -The ``FitHook`` class is used by a ``FitRecipe`` to report fit progress to a -user. ``FitHook`` can be found in the ``diffpy.srfit.fitbase.fithook`` module. -``FitHook`` can be customized to provide customized fit output, such as a live -plot of the output. The ``FitHook`` class has three methods that one can -overload. - -.. currentmodule:: diffpy.srfit.fitbase.fithook - -* .. automethod:: FitHook.reset -* .. automethod:: FitHook.precall -* .. automethod:: FitHook.postcall - -To use a custom ``FitHook``, assign an instance to a ``FitRecipe`` using the -``pushFitHook`` method. All ``FitHook`` instances held by a ``FitRecipe`` will -be used in sequence during a call to ``FitRecipe.residual``. diff --git a/doc/manual/source/index.rst b/doc/manual/source/index.rst deleted file mode 100644 index ea21479d..00000000 --- a/doc/manual/source/index.rst +++ /dev/null @@ -1,84 +0,0 @@ -.. _developers-guide-index: - -#################################################### -diffpy.srfit documentation -#################################################### - -diffpy.srfit - configurable code for solving atomic structures. - -| Software version |release|. -| Last updated |today|. - -The diffpy.srfit package provides the framework for building a global optimizer -on the fly from components such as function calculators (that calculate -different data spectra), regression algorithms and structure models. The -software is capable of co-refinement using multiple information sources or -models. It provides a uniform interface for various regression algorithms. The -target function being optimized can be specified by the user according to the -data available. - -Within the diffpy.srfit framework, any parameter used in describing the -structure of a material can be passed as a refinable variable to the global -optimizer. Once parameters are declared as variables they can easily be turned -"on" or "off", i.e. fixed or allowed to vary. Additionally, variables may be -constrained to obey mathematical relationships with other parameters or -variables used in the structural model. Restraints can be applied to -variables, which adds a penalty to the refinement process commensurate with the -deviation from the known value or range. The cost function can also be -customized by the user. If the refinement contains multiple models, each model -can have its own cost function which will be properly weighted and combined to -obtain the total cost function. Additionally, diffpy.srfit is designed to be -extensible, allowing the user to integrate external calculators to perform -co-refinements with other techniques. - -======================================== -Authors -======================================== - -diffpy.srfit is developed by members of the Billinge Group at -Columbia University and at Brookhaven National Laboratory including -Christopher L. Farrow, Pavol Juhás, Simon J.L. Billinge. - -The source code in *observable.py* was derived from the 1.0 version -of the Caltech "Pyre" project. - -For a detailed list of contributors see -https://github.com/diffpy/diffpy.srfit/graphs/contributors. - -====================================== -Installation -====================================== - -See the `README `_ -file included with the distribution. - -====================================== -Where next? -====================================== - -.. toctree:: - :maxdepth: 2 - - examples.rst - extending.rst - -====================================== -Table of contents -====================================== - -.. toctree:: - :titlesonly: - - license - release - Package API - -.. faq.rst - -====================================== -Indices -====================================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/doc/manual/source/license.rst b/doc/manual/source/license.rst deleted file mode 100644 index 7d78e94f..00000000 --- a/doc/manual/source/license.rst +++ /dev/null @@ -1,142 +0,0 @@ -.. index:: license - -License -####### - -OPEN SOURCE LICENSE AGREEMENT -============================= - -| Copyright (c) 2009-2011, University of Tennessee -| Copyright (c) 1989, 1991 Free Software Foundation, Inc. -| Copyright (c) 2006, The Regents of the University of California through - Lawrence Berkeley National Laboratory -| Copyright (c) 2014, Australian Synchrotron Research Program Inc., ("ASRP") -| Copyright (c) 2006-2007, Board of Trustees of Michigan State University -| Copyright (c) 2008-2012, The Trustees of Columbia University in - the City of New York -| Copyright (c) 2014-2019, Brookhaven Science Associates, - Brookhaven National Laboratory - - -The "DiffPy-CMI" is distributed subject to the following license conditions: - - -SOFTWARE LICENSE AGREEMENT -========================== - -Software: **DiffPy-CMI** - - -(1) The "Software", below, refers to the aforementioned DiffPy-CMI (in either -source code, or binary form and accompanying documentation). - -Part of the software was derived from the DANSE, ObjCryst++ (with permission), -PyCifRW, Python periodictable, CCTBX, and SasView open source projects, of -which the original Copyrights are contained in each individual file. - -Each licensee is addressed as "you" or "Licensee." - - -(2) The copyright holders shown above and their third-party Licensors hereby -grant licensee a royalty-free nonexclusive license, subject to the limitations -stated herein and U.S. Government license rights. - - -(3) You may modify and make a copy or copies of the software for use within -your organization, if you meet the following conditions: - - (a) Copies in source code must include the copyright notice and this - software license agreement. - - (b) Copies in binary form must include the copyright notice and this - Software License Agreement in the documentation and/or other materials - provided with the copy. - - -(4) You may modify a copy or copies of the Software or any portion of it, thus -forming a work based on the Software, and distribute copies of such work -outside your organization, if you meet all of the following conditions: - - (a) Copies in source code must include the copyright notice and this - Software License Agreement; - - (b) Copies in binary form must include the copyright notice and this - Software License Agreement in the documentation and/or other materials - provided with the copy; - - (c) Modified copies and works based on the Software must carry prominent - notices stating that you changed specified portions of the Software. - - (d) Neither the name of Brookhaven Science Associates or Brookhaven - National Laboratory nor the names of its contributors may be used to - endorse or promote products derived from this software without specific - written permission. - - -(5) Portions of the Software resulted from work developed under a U.S. -Government contract and are subject to the following license: -The Government is granted for itself and others acting on its behalf a -paid-up, nonexclusive, irrevocable worldwide license in this computer software -to reproduce, prepare derivative works, and perform publicly and display -publicly. - - -(6) WARRANTY DISCLAIMER. THE SOFTWARE IS SUPPLIED "AS IS" WITHOUT -WARRANTY OF ANY KIND. THE COPYRIGHT HOLDERS, THEIR THIRD PARTY -LICENSORS, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF ENERGY, AND -THEIR EMPLOYEES: (1) DISCLAIM ANY WARRANTIES, EXPRESS OR IMPLIED, INCLUDING -BUT NOT LIMITED TO ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE, TITLE OR NON-INFRINGEMENT, (2) DO NOT ASSUME ANY LEGAL -LIABILITY OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR USEFULNESS OF -THE SOFTWARE, (3) DO NOT REPRESENT THAT USE OF THE SOFTWARE WOULD NOT INFRINGE -PRIVATELY OWNED RIGHTS, (4) DO NOT WARRANT THAT THE SOFTWARE WILL FUNCTION -UNINTERRUPTED, THAT IT IS ERROR-FREE OR THAT ANY ERRORS WILL BE CORRECTED. - - -(7) LIMITATION OF LIABILITY. IN NO EVENT WILL THE COPYRIGHT HOLDERS, THEIR -THIRD PARTY LICENSORS, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF -ENERGY, OR THEIR EMPLOYEES: BE LIABLE FOR ANY INDIRECT, INCIDENTAL, -CONSEQUENTIAL, SPECIAL OR PUNITIVE DAMAGES OF ANY KIND OR NATURE, INCLUDING -BUT NOT LIMITED TO LOSS OF PROFITS OR LOSS OF DATA, FOR ANY REASON WHATSOEVER, -WHETHER SUCH LIABILITY IS ASSERTED ON THE BASIS OF CONTRACT, TORT (INCLUDING -NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE, EVEN IF ANY OF SAID PARTIES HAS -BEEN WARNED OF THE POSSIBILITY OF SUCH LOSS OR DAMAGES. - - -Brookhaven National Laboratory Notice -===================================== - -Acknowledgment of sponsorship ------------------------------ - -This software was produced by the Brookhaven National Laboratory, under -Contract DE-AC02-98CH10886 with the Department of Energy. - - -Government disclaimer of liability ----------------------------------- - -Neither the United States nor the United States Department of Energy, nor -any of their employees, makes any warranty, express or implied, or assumes -any legal liability or responsibility for the accuracy, completeness, or -usefulness of any data, apparatus, product, or process disclosed, or -represents that its use would not infringe privately owned rights. - - -Brookhaven disclaimer of liability ----------------------------------- - -Brookhaven National Laboratory makes no representations or warranties, -express or implied, nor assumes any liability for the use of this software. - - -Maintenance of notice ---------------------- - -In the interest of clarity regarding the origin and status of this -software, Brookhaven National Laboratory requests that any recipient of it -maintain this notice affixed to any distribution by the recipient that -contains a copy or derivative of this software. - - -.. rubric:: END OF LICENSE diff --git a/doc/manual/source/release.rst b/doc/manual/source/release.rst deleted file mode 100644 index 7ec4f81d..00000000 --- a/doc/manual/source/release.rst +++ /dev/null @@ -1,3 +0,0 @@ -.. index:: release notes - -.. mdinclude:: ../../../CHANGELOG.md From a968a847861144ddd66325db5fa8e595cdfd38d8 Mon Sep 17 00:00:00 2001 From: Tieqiong Zhang Date: Tue, 2 Jul 2024 12:22:28 -0400 Subject: [PATCH 03/21] Update doc source relative path --- doc/source/examples.rst | 2 +- doc/source/examples/coreshellnp.rst | 2 +- doc/source/examples/crystalpdf.rst | 2 +- doc/source/examples/crystalpdfall.rst | 2 +- doc/source/examples/crystalpdfobjcryst.rst | 2 +- doc/source/examples/crystalpdftwodata.rst | 2 +- doc/source/examples/crystalpdftwophase.rst | 2 +- doc/source/examples/debyemodel.rst | 2 +- doc/source/examples/debyemodelII.rst | 2 +- doc/source/examples/ellipsoidsas.rst | 2 +- doc/source/examples/gaussiangenerator.rst | 2 +- doc/source/examples/gaussianrecipe.rst | 2 +- doc/source/examples/interface.rst | 2 +- doc/source/examples/npintensity.rst | 2 +- doc/source/examples/npintensityII.rst | 2 +- doc/source/examples/nppdfcrystal.rst | 2 +- doc/source/examples/nppdfobjcryst.rst | 2 +- doc/source/examples/nppdfsas.rst | 2 +- doc/source/examples/simplepdf.rst | 2 +- doc/source/examples/simplepdftwophase.rst | 2 +- doc/source/examples/simplerecipe.rst | 2 +- doc/source/extending.rst | 6 +++--- 22 files changed, 24 insertions(+), 24 deletions(-) diff --git a/doc/source/examples.rst b/doc/source/examples.rst index 2403d1b8..b599e568 100644 --- a/doc/source/examples.rst +++ b/doc/source/examples.rst @@ -4,7 +4,7 @@ Examples =================== -.. include:: ../../examples/README +.. include:: ../examples/README .. This creates the links from the filenames within README to pages. .. _gaussianrecipe.py: examples/gaussianrecipe.html diff --git a/doc/source/examples/coreshellnp.rst b/doc/source/examples/coreshellnp.rst index d8a84e0f..334234cc 100644 --- a/doc/source/examples/coreshellnp.rst +++ b/doc/source/examples/coreshellnp.rst @@ -4,4 +4,4 @@ coreshellnp.py ======================== -.. literalinclude:: ../../../examples/coreshellnp.py +.. literalinclude:: ../../examples/coreshellnp.py diff --git a/doc/source/examples/crystalpdf.rst b/doc/source/examples/crystalpdf.rst index 51ef5185..36cfb8f6 100644 --- a/doc/source/examples/crystalpdf.rst +++ b/doc/source/examples/crystalpdf.rst @@ -4,4 +4,4 @@ crystalpdf.py ======================== -.. literalinclude:: ../../../examples/crystalpdf.py +.. literalinclude:: ../../examples/crystalpdf.py diff --git a/doc/source/examples/crystalpdfall.rst b/doc/source/examples/crystalpdfall.rst index b2f74fb8..68a5584a 100644 --- a/doc/source/examples/crystalpdfall.rst +++ b/doc/source/examples/crystalpdfall.rst @@ -4,4 +4,4 @@ crystalpdfall.py ======================== -.. literalinclude:: ../../../examples/crystalpdfall.py +.. literalinclude:: ../../examples/crystalpdfall.py diff --git a/doc/source/examples/crystalpdfobjcryst.rst b/doc/source/examples/crystalpdfobjcryst.rst index 4542b65a..6badf9f4 100644 --- a/doc/source/examples/crystalpdfobjcryst.rst +++ b/doc/source/examples/crystalpdfobjcryst.rst @@ -4,4 +4,4 @@ crystalpdfobjcryst.py ======================== -.. literalinclude:: ../../../examples/crystalpdfobjcryst.py +.. literalinclude:: ../../examples/crystalpdfobjcryst.py diff --git a/doc/source/examples/crystalpdftwodata.rst b/doc/source/examples/crystalpdftwodata.rst index 9b42e45f..a2e76eb0 100644 --- a/doc/source/examples/crystalpdftwodata.rst +++ b/doc/source/examples/crystalpdftwodata.rst @@ -4,4 +4,4 @@ crystalpdftwodata.py ======================== -.. literalinclude:: ../../../examples/crystalpdftwodata.py +.. literalinclude:: ../../examples/crystalpdftwodata.py diff --git a/doc/source/examples/crystalpdftwophase.rst b/doc/source/examples/crystalpdftwophase.rst index eb2cf18b..50a5eb21 100644 --- a/doc/source/examples/crystalpdftwophase.rst +++ b/doc/source/examples/crystalpdftwophase.rst @@ -4,4 +4,4 @@ crystalpdftwophase.py ======================== -.. literalinclude:: ../../../examples/crystalpdftwophase.py +.. literalinclude:: ../../examples/crystalpdftwophase.py diff --git a/doc/source/examples/debyemodel.rst b/doc/source/examples/debyemodel.rst index 436d20ca..1f85ea6d 100644 --- a/doc/source/examples/debyemodel.rst +++ b/doc/source/examples/debyemodel.rst @@ -4,4 +4,4 @@ debyemodel.py ======================== -.. literalinclude:: ../../../examples/debyemodel.py +.. literalinclude:: ../../examples/debyemodel.py diff --git a/doc/source/examples/debyemodelII.rst b/doc/source/examples/debyemodelII.rst index d44cc60d..3345c4a0 100644 --- a/doc/source/examples/debyemodelII.rst +++ b/doc/source/examples/debyemodelII.rst @@ -4,4 +4,4 @@ debyemodelII.py ======================== -.. literalinclude:: ../../../examples/debyemodelII.py +.. literalinclude:: ../../examples/debyemodelII.py diff --git a/doc/source/examples/ellipsoidsas.rst b/doc/source/examples/ellipsoidsas.rst index 132b2ee7..e885f1ef 100644 --- a/doc/source/examples/ellipsoidsas.rst +++ b/doc/source/examples/ellipsoidsas.rst @@ -4,4 +4,4 @@ ellipsoidsas.py ======================== -.. literalinclude:: ../../../examples/ellipsoidsas.py +.. literalinclude:: ../../examples/ellipsoidsas.py diff --git a/doc/source/examples/gaussiangenerator.rst b/doc/source/examples/gaussiangenerator.rst index eb101bb9..dc459834 100644 --- a/doc/source/examples/gaussiangenerator.rst +++ b/doc/source/examples/gaussiangenerator.rst @@ -4,4 +4,4 @@ gaussiangenerator.py ======================== -.. literalinclude:: ../../../examples/gaussiangenerator.py +.. literalinclude:: ../../examples/gaussiangenerator.py diff --git a/doc/source/examples/gaussianrecipe.rst b/doc/source/examples/gaussianrecipe.rst index 73f94eac..7b0eaa1a 100644 --- a/doc/source/examples/gaussianrecipe.rst +++ b/doc/source/examples/gaussianrecipe.rst @@ -4,4 +4,4 @@ gaussianrecipe.py ======================== -.. literalinclude:: ../../../examples/gaussianrecipe.py +.. literalinclude:: ../../examples/gaussianrecipe.py diff --git a/doc/source/examples/interface.rst b/doc/source/examples/interface.rst index 41e706a8..c43db23a 100644 --- a/doc/source/examples/interface.rst +++ b/doc/source/examples/interface.rst @@ -4,4 +4,4 @@ interface.py ======================== -.. literalinclude:: ../../../examples/interface.py +.. literalinclude:: ../../examples/interface.py diff --git a/doc/source/examples/npintensity.rst b/doc/source/examples/npintensity.rst index be8705eb..ce9ca226 100644 --- a/doc/source/examples/npintensity.rst +++ b/doc/source/examples/npintensity.rst @@ -4,4 +4,4 @@ npintensity.py ======================== -.. literalinclude:: ../../../examples/npintensity.py +.. literalinclude:: ../../examples/npintensity.py diff --git a/doc/source/examples/npintensityII.rst b/doc/source/examples/npintensityII.rst index 0fb043ea..56750adc 100644 --- a/doc/source/examples/npintensityII.rst +++ b/doc/source/examples/npintensityII.rst @@ -4,4 +4,4 @@ npintensityII.py ======================== -.. literalinclude:: ../../../examples/npintensityII.py +.. literalinclude:: ../../examples/npintensityII.py diff --git a/doc/source/examples/nppdfcrystal.rst b/doc/source/examples/nppdfcrystal.rst index 38bd3523..44640074 100644 --- a/doc/source/examples/nppdfcrystal.rst +++ b/doc/source/examples/nppdfcrystal.rst @@ -4,4 +4,4 @@ nppdfcrystal.py ======================== -.. literalinclude:: ../../../examples/nppdfcrystal.py +.. literalinclude:: ../../examples/nppdfcrystal.py diff --git a/doc/source/examples/nppdfobjcryst.rst b/doc/source/examples/nppdfobjcryst.rst index c5ba169e..977b156c 100644 --- a/doc/source/examples/nppdfobjcryst.rst +++ b/doc/source/examples/nppdfobjcryst.rst @@ -4,4 +4,4 @@ nppdfobjcryst.py ======================== -.. literalinclude:: ../../../examples/nppdfobjcryst.py +.. literalinclude:: ../../examples/nppdfobjcryst.py diff --git a/doc/source/examples/nppdfsas.rst b/doc/source/examples/nppdfsas.rst index 26852a89..48564ed3 100644 --- a/doc/source/examples/nppdfsas.rst +++ b/doc/source/examples/nppdfsas.rst @@ -4,4 +4,4 @@ nppdfsas.py ======================== -.. literalinclude:: ../../../examples/nppdfsas.py +.. literalinclude:: ../../examples/nppdfsas.py diff --git a/doc/source/examples/simplepdf.rst b/doc/source/examples/simplepdf.rst index a926db37..6b959a5c 100644 --- a/doc/source/examples/simplepdf.rst +++ b/doc/source/examples/simplepdf.rst @@ -4,4 +4,4 @@ simplepdf.py ======================== -.. literalinclude:: ../../../examples/simplepdf.py +.. literalinclude:: ../../examples/simplepdf.py diff --git a/doc/source/examples/simplepdftwophase.rst b/doc/source/examples/simplepdftwophase.rst index 8e61dec2..acde5190 100644 --- a/doc/source/examples/simplepdftwophase.rst +++ b/doc/source/examples/simplepdftwophase.rst @@ -4,4 +4,4 @@ simplepdftwophase.py ======================== -.. literalinclude:: ../../../examples/simplepdftwophase.py +.. literalinclude:: ../../examples/simplepdftwophase.py diff --git a/doc/source/examples/simplerecipe.rst b/doc/source/examples/simplerecipe.rst index 046b09cd..e79a2e09 100644 --- a/doc/source/examples/simplerecipe.rst +++ b/doc/source/examples/simplerecipe.rst @@ -4,4 +4,4 @@ simplerecipe.py ======================== -.. literalinclude:: ../../../examples/simplerecipe.py +.. literalinclude:: ../../examples/simplerecipe.py diff --git a/doc/source/extending.rst b/doc/source/extending.rst index 5aa596eb..464cd16c 100644 --- a/doc/source/extending.rst +++ b/doc/source/extending.rst @@ -180,7 +180,7 @@ external program before or after interfacing with SrFit. An example of a customized Profile is the ``SASProfile`` class in the ``diffpy.srfit.sas.sasprofile`` module: -.. literalinclude:: ../../../src/diffpy/srfit/sas/sasprofile.py +.. literalinclude:: ../../src/diffpy/srfit/sas/sasprofile.py :pyobject: SASProfile The ``__init__`` method sets the ``xobs``, ``yobs`` and ``dyobs`` attributes of @@ -218,7 +218,7 @@ to keep the restraint cost comparable to the residual of a single data point. ``Restraint`` whose penalty is the root-mean-square deviation from the expected and calculated BVS of a structure. -.. literalinclude:: ../../../src/diffpy/srfit/structure/bvsrestraint.py +.. literalinclude:: ../../src/diffpy/srfit/structure/bvsrestraint.py :pyobject: BVSRestraint Note that the penalty scaling is optional (selected by the `scaled` flag) and @@ -230,7 +230,7 @@ restrainable object. A ``BVSRestraint`` is used to restrain a ``SrRealParSet``, which is a ``ParameterSet`` wrapper base class for SrReal-compatible structures. The restraint is applied with the ``restrainBVS`` method. -.. literalinclude:: ../../../src/diffpy/srfit/structure/srrealparset.py +.. literalinclude:: ../../src/diffpy/srfit/structure/srrealparset.py :pyobject: SrRealParSet.restrainBVS The purpose of the method is to create the custom ``Restraint`` object, From 53fc98a2cab7370fa58b34226b2f768613f69bc7 Mon Sep 17 00:00:00 2001 From: Tieqiong Zhang Date: Tue, 2 Jul 2024 12:50:26 -0400 Subject: [PATCH 04/21] remove conda-recipe --- conda-recipe/bld.bat | 7 --- conda-recipe/build.sh | 8 ---- conda-recipe/conda_build_config.yaml | 5 --- conda-recipe/meta.yaml | 66 ---------------------------- conda-recipe/run_test.py | 4 -- 5 files changed, 90 deletions(-) delete mode 100644 conda-recipe/bld.bat delete mode 100644 conda-recipe/build.sh delete mode 100644 conda-recipe/conda_build_config.yaml delete mode 100644 conda-recipe/meta.yaml delete mode 100644 conda-recipe/run_test.py diff --git a/conda-recipe/bld.bat b/conda-recipe/bld.bat deleted file mode 100644 index 0a79fa23..00000000 --- a/conda-recipe/bld.bat +++ /dev/null @@ -1,7 +0,0 @@ -"%PYTHON%" setup.py install -if errorlevel 1 exit 1 - -:: Add more build steps here, if they are necessary. - -:: See http://docs.continuum.io/conda/build.html -:: for a list of environment variables that are set during the build process. diff --git a/conda-recipe/build.sh b/conda-recipe/build.sh deleted file mode 100644 index b7920393..00000000 --- a/conda-recipe/build.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -$PYTHON setup.py install - -# Add more build steps here, if they are necessary. - -# See http://docs.continuum.io/conda/build.html -# for a list of environment variables that are set during the build process. diff --git a/conda-recipe/conda_build_config.yaml b/conda-recipe/conda_build_config.yaml deleted file mode 100644 index 8d446529..00000000 --- a/conda-recipe/conda_build_config.yaml +++ /dev/null @@ -1,5 +0,0 @@ -python: - - 3.7 - - 3.6 - - 3.5 - - 2.7 diff --git a/conda-recipe/meta.yaml b/conda-recipe/meta.yaml deleted file mode 100644 index d3c86a23..00000000 --- a/conda-recipe/meta.yaml +++ /dev/null @@ -1,66 +0,0 @@ -{% set setupdata = load_setup_py_data() %} - -package: - name: diffpy.srfit - version: {{ setupdata['version'] }} - -source: - git_url: .. - -build: - preserve_egg_dir: True - - # If this is a new build for the same version, increment the build - # number. If you do not include this key, it defaults to 0. - # number: 0 - -requirements: - build: - - python {{ python }} - - setuptools - - six - - run: - - python - - setuptools - - numpy >=1.11 - - six - -test: - # Python imports - imports: - - diffpy.srfit - - diffpy.srfit.equation - - diffpy.srfit.equation.literals - - diffpy.srfit.equation.visitors - - diffpy.srfit.fitbase - - diffpy.srfit.interface - - diffpy.srfit.pdf - - diffpy.srfit.sas - - diffpy.srfit.structure - - diffpy.srfit.tests - - diffpy.srfit.util - - commands: - # You can put test commands to be run here. Use this to test that the - # entry points work. - - # You can also put a file called run_test.py in the recipe that will be run - # at test time. - - requires: - # Put any additional test requirements here. For example - - diffpy.structure - - pyobjcryst - - diffpy.srreal - # FIXME - correct when packages become available for Python 3. - - srfit-sasview # [py2k] - -about: - home: https://github.com/diffpy/diffpy.srfit/ - summary: Framework for complex modeling and atomic structure optimization. - license: Modified BSD License - license_file: LICENSE.txt - -# See http://docs.continuum.io/conda/build.html -# for more information about meta.yaml. diff --git a/conda-recipe/run_test.py b/conda-recipe/run_test.py deleted file mode 100644 index 545d32fa..00000000 --- a/conda-recipe/run_test.py +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env python - -import diffpy.srfit.tests -assert diffpy.srfit.tests.test().wasSuccessful() From 543aeda320578ce87977ec2792e7bf0396c5f884 Mon Sep 17 00:00:00 2001 From: Tieqiong Zhang Date: Tue, 2 Jul 2024 12:52:17 -0400 Subject: [PATCH 05/21] remove gitarchive, travis, setup --- .gitarchive.cfg | 5 -- .travis.yml | 123 ---------------------------------------------- setup.py | 127 ------------------------------------------------ 3 files changed, 255 deletions(-) delete mode 100644 .gitarchive.cfg delete mode 100644 .travis.yml delete mode 100755 setup.py diff --git a/.gitarchive.cfg b/.gitarchive.cfg deleted file mode 100644 index 95e1448c..00000000 --- a/.gitarchive.cfg +++ /dev/null @@ -1,5 +0,0 @@ -[DEFAULT] -commit = $Format:%H$ -date = $Format:%ci$ -timestamp = $Format:%ct$ -refnames = $Format:%D$ diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a3469af5..00000000 --- a/.travis.yml +++ /dev/null @@ -1,123 +0,0 @@ -dist: xenial -language: generic - -os: - - linux - - osx - -env: - - MYUSEMC=true MYPYTHON_VERSION=2.7 - - MYUSEMC=true MYPYTHON_VERSION=3.5 - - MYUSEMC=true MYPYTHON_VERSION=3.6 - - MYUSEMC=true MYPYTHON_VERSION=3.7 - - MYUSEMC=false - -git: - depth: 999999 - -branches: - except: - - /^v[0-9]/ - - -before_install: - - MYNAME=diffpy.srfit - - MYCOMMIT="$(git rev-parse HEAD)" - - umask 022 - - git fetch origin --tags - - MYPYTHON=python; MYPIP=pip - - NOSYS=true; NOAPT=true; NOBREW=true; NOMC=true - - if ${MYUSEMC}; then - NOMC=false; - elif [[ ${TRAVIS_OS_NAME} == linux ]]; then - NOAPT=false; NOSYS=false; - MYPIPFLAGS="--user"; - elif [[ ${TRAVIS_OS_NAME} == osx ]]; then - NOBREW=false; NOSYS=false; - MYPYTHON=python3; - MYPIP=pip3; - MYPIPFLAGS="--user"; - fi - - MYMCREPO=https://repo.anaconda.com/miniconda - - case ${TRAVIS_OS_NAME} in - linux) - MYMCBUNDLE=Miniconda3-latest-Linux-x86_64.sh ;; - osx) - MYMCBUNDLE=Miniconda3-latest-MacOSX-x86_64.sh ;; - *) - echo "Unsupported operating system." >&2; - exit 2 ;; - esac - - MYRUNDIR=${PWD}/build/rundir - - - mkdir -p ~/pkgs - - mkdir -p ${MYRUNDIR} - - cp .coveragerc ${MYRUNDIR}/ - - - $NOMC || pushd ~/pkgs - - $NOMC || wget --timestamping ${MYMCREPO}/${MYMCBUNDLE} - - $NOMC || test -x ~/mc/bin/conda || bash ${MYMCBUNDLE} -b -f -p ~/mc - - $NOMC || popd - - $NOMC || source ~/mc/bin/activate base - - $NOMC || conda update --yes conda - - $NOMC || conda install --yes conda-build conda-verify jinja2 - - $NOMC || conda create --name=testenv --yes python=${MYPYTHON_VERSION} coverage - - $NOMC || conda config --add channels diffpy - - - $NOAPT || test "${TRAVIS_OS_NAME}" = "linux" || exit $? - - $NOAPT || PATH="$(echo "$PATH" | sed 's,:/opt/pyenv/[^:]*,,g')" - - $NOAPT || test "$(which python)" = "/usr/bin/python" || ( - which python; exit 1) - - $NOAPT || sudo apt-get update -qq - - $NOAPT || sudo apt-get install -y - python-dev python-setuptools python-numpy - build-essential - - - $NOBREW || test "${TRAVIS_OS_NAME}" = "osx" || exit $? - - $NOBREW || brew update - - $NOBREW || brew upgrade python - - $NOBREW || brew install gcc || brew link --overwrite gcc - - - $NOSYS || devutils/makesdist - - $NOSYS || MYTARBUNDLE="$(ls -t "${PWD}"/dist/*.tar.gz | head -1)" - - -install: - - $NOMC || conda build --python=${MYPYTHON_VERSION} conda-recipe - - $NOMC || conda render --python=${MYPYTHON_VERSION} --output conda-recipe | - sed 's,.*/,,; s/[.]tar[.]bz2$//; s/-/=/g' > /tmp/mypackage.txt - - $NOMC || source activate testenv - - $NOMC || conda install --yes --use-local --file=/tmp/mypackage.txt - - $NOMC || conda install --yes - diffpy.structure pyobjcryst "diffpy.srreal>=1.3.0" - # TODO - always install srfit-sasview when ready for Python 3. - - if $MYUSEMC && [[ "$MYPYTHON_VERSION" == 2.7 ]]; then - conda install --yes srfit-sasview; - fi - - - $NOSYS || $MYPIP install $MYPIPFLAGS coverage - - $NOSYS || $MYPIP install $MYPIPFLAGS pycifrw - - $NOSYS || $MYPIP install $MYPIPFLAGS diffpy.structure - - $NOSYS || $MYPIP install $MYPIPFLAGS "${MYTARBUNDLE}" - - - cd ${MYRUNDIR} - - MYGIT_REV=$($MYPYTHON -c "import ${MYNAME}.version as v; print(v.__git_commit__)") - - if [[ "${MYCOMMIT}" != "${MYGIT_REV}" ]]; then - echo "Version mismatch ${MYCOMMIT} vs ${MYGIT_REV}."; - exit 1; - fi - - -before_script: - - $NOBREW || USER_BASE="$(python3 -c 'import site; print(site.USER_BASE)')" - - $NOBREW || PATH="${USER_BASE}/bin:${PATH}" - - -script: - - coverage run --source ${MYNAME} -m ${MYNAME}.tests.run - - -after_success: - # do not post coverage reports when testing with system Python. - - $NOMC || $MYPIP install $MYPIPFLAGS codecov - - $NOMC || codecov diff --git a/setup.py b/setup.py deleted file mode 100755 index d3577dd2..00000000 --- a/setup.py +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env python - -# Installation script for diffpy.srfit - -"""diffpy.srfit - framework for setting up complex modeling refinements. - -Packages: diffpy.srfit -""" - -import os -import re -import sys -from setuptools import setup, find_packages - -# Use this version when git data are not available, like in git zip archive. -# Update when tagging a new release. -FALLBACK_VERSION = '3.0.0.post0' - -# determine if we run with Python 3. -PY3 = (sys.version_info[0] == 3) - -# versioncfgfile holds version data for git commit hash and date. -# It must reside in the same directory as version.py. -MYDIR = os.path.dirname(os.path.abspath(__file__)) -versioncfgfile = os.path.join(MYDIR, 'src/diffpy/srfit/version.cfg') -gitarchivecfgfile = os.path.join(MYDIR, '.gitarchive.cfg') - -def gitinfo(): - from subprocess import Popen, PIPE - kw = dict(stdout=PIPE, cwd=MYDIR, universal_newlines=True) - proc = Popen(['git', 'describe', '--match=v[[:digit:]]*'], **kw) - desc = proc.stdout.read() - proc = Popen(['git', 'log', '-1', '--format=%H %ct %ci'], **kw) - glog = proc.stdout.read() - rv = {} - rv['version'] = '.post'.join(desc.strip().split('-')[:2]).lstrip('v') - rv['commit'], rv['timestamp'], rv['date'] = glog.strip().split(None, 2) - return rv - - -def getversioncfg(): - if PY3: - from configparser import RawConfigParser - else: - from ConfigParser import RawConfigParser - vd0 = dict(version=FALLBACK_VERSION, commit='', date='', timestamp=0) - # first fetch data from gitarchivecfgfile, ignore if it is unexpanded - g = vd0.copy() - cp0 = RawConfigParser(vd0) - cp0.read(gitarchivecfgfile) - if len(cp0.get('DEFAULT', 'commit')) > 20: - g = cp0.defaults() - mx = re.search(r'\btag: v(\d[^,]*)', g.pop('refnames')) - if mx: - g['version'] = mx.group(1) - # then try to obtain version data from git. - gitdir = os.path.join(MYDIR, '.git') - if os.path.exists(gitdir) or 'GIT_DIR' in os.environ: - try: - g = gitinfo() - except OSError: - pass - # finally, check and update the active version file - cp = RawConfigParser() - cp.read(versioncfgfile) - d = cp.defaults() - rewrite = not d or (g['commit'] and ( - g['version'] != d.get('version') or g['commit'] != d.get('commit'))) - if rewrite: - cp.set('DEFAULT', 'version', g['version']) - cp.set('DEFAULT', 'commit', g['commit']) - cp.set('DEFAULT', 'date', g['date']) - cp.set('DEFAULT', 'timestamp', g['timestamp']) - with open(versioncfgfile, 'w') as fp: - cp.write(fp) - return cp - -versiondata = getversioncfg() - -with open(os.path.join(MYDIR, 'README.rst')) as fp: - long_description = fp.read() - -# define distribution -setup_args = dict( - name = "diffpy.srfit", - version = versiondata.get('DEFAULT', 'version'), - packages = find_packages(os.path.join(MYDIR, 'src')), - package_dir = {'' : 'src'}, - test_suite = 'diffpy.srfit.tests', - include_package_data = True, - install_requires = ['six'], - zip_safe = False, - author = "Simon J.L. Billinge", - author_email = "sb2896@columbia.edu", - maintainer = "Pavol Juhas", - maintainer_email = "pavol.juhas@gmail.com", - description = "SrFit - Structure refinement from diffraction data", - long_description = long_description, - long_description_content_type = 'text/x-rst', - license = 'BSD-style license', - url = "https://github.com/diffpy/diffpy.srfit", - keywords = "optimization constraints restraints structure refinement complex modeling", - classifiers = [ - # List of possible values at - # http://pypi.python.org/pypi?:action=list_classifiers - 'Development Status :: 5 - Production/Stable', - 'Environment :: Console', - 'Intended Audience :: Developers', - 'Intended Audience :: Education', - 'Intended Audience :: Science/Research', - 'License :: OSI Approved :: BSD License', - 'Operating System :: MacOS', - 'Operating System :: POSIX', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Topic :: Scientific/Engineering :: Chemistry', - 'Topic :: Scientific/Engineering :: Physics', - 'Topic :: Software Development :: Libraries', - ], -) - -if __name__ == '__main__': - setup(**setup_args) - -# End of file From 042c7cdefe4b9c79bf8a1e0b9a8ed7ef9922dcd6 Mon Sep 17 00:00:00 2001 From: Tieqiong Zhang Date: Tue, 2 Jul 2024 12:55:24 -0400 Subject: [PATCH 06/21] modify codecov, gitignore --- .codecov.yml | 5 +-- .gitignore | 88 ++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 75 insertions(+), 18 deletions(-) diff --git a/.codecov.yml b/.codecov.yml index 70686df3..04dd6510 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -10,7 +10,7 @@ coverage: status: patch: default: - target: '80' + target: '70' if_no_uploads: error if_not_found: success if_ci_failed: failure @@ -20,12 +20,13 @@ coverage: target: auto if_no_uploads: error if_not_found: success - if_ci_failed: failure + if_ci_failed: error paths: '!*/tests/.*' tests: target: 97.9% paths: '*/tests/.*' + if_not_found: success flags: tests: diff --git a/.gitignore b/.gitignore index 9f5ecbf0..5ca5b5a6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,37 +1,59 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ *.py[cod] +*$py.class # C extensions *.so -# Packages -*.egg -*.egg-info -dist -build -eggs -parts -bin -var -sdist -temp -develop-eggs +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +venv/ +*.egg-info/ .installed.cfg -lib -lib64 -tags +*.egg +bin/ +temp/ +tags/ errors.err +# 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 MANIFEST # Unit test / coverage reports +htmlcov/ +.tox/ .coverage -.tox +.coverage.* +.cache nosetests.xml +coverage.xml +*,cover +.hypothesis/ # Translations *.mo +*.pot # Mr Developer .mr.developer.cfg @@ -39,6 +61,40 @@ nosetests.xml .pydevproject .settings +# Django stuff: +*.log + +# Sphinx documentation +docs/build/ +docs/source/generated/ + +# pytest +.pytest_cache/ + +# PyBuilder +target/ + +# Editor files +# mac +.DS_Store +*~ + +# vim +*.swp +*.swo + +# pycharm +.idea/ + +# VSCode +.vscode/ + +# Ipython Notebook +.ipynb_checkpoints + # version information setup.cfg /src/diffpy/*/version.cfg + +# Rever +rever/ From f9d80e7096d2a1093ceb4b6b5968ceae9f8712e9 Mon Sep 17 00:00:00 2001 From: Tieqiong Zhang Date: Tue, 2 Jul 2024 12:55:59 -0400 Subject: [PATCH 07/21] Use new coveragerc, gitattributes --- .coveragerc | 31 +++++++++++-------------------- .gitattributes | 8 +------- 2 files changed, 12 insertions(+), 27 deletions(-) diff --git a/.coveragerc b/.coveragerc index d0a0d16d..fe3daa8e 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,22 +1,13 @@ -# Configuration of the coverage.py tool for reporting test coverage. - -[report] -# RE patterns for lines to be excluded from consideration. -exclude_lines = - ## Have to re-enable the standard pragma - pragma: no cover - ## Don't complain if tests don't hit defensive assertion code: - raise AssertionError - raise NotImplementedError - ^[ ]*assert False - - ## Don't complain if non-runnable code isn't run: - ^[ ]*@unittest.skip\b - ^[ ]{4}unittest.main() - if __name__ == .__main__.: - - [run] +source = + diffpy.srfit +[report] omit = - ## exclude debug.py from codecov report - */tests/debug.py + */python?.?/* + */site-packages/nose/* + # ignore _version.py and versioneer.py + .*version.* + *_version.py + +exclude_lines = + if __name__ == '__main__': diff --git a/.gitattributes b/.gitattributes index 9d58a8cd..691465b5 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,7 +1 @@ -/.gitattributes export-ignore -/.gitignore export-ignore -/.travis.yml export-ignore -/conda-recipe/ export-ignore -/devutils export-ignore -.gitarchive.cfg export-subst -*.bat text eol=crlf +diffpy.srfit/_version.py export-subst From a7fd98ec1c985a2b1a6eed34268b308270c4e512 Mon Sep 17 00:00:00 2001 From: Tieqiong Zhang Date: Tue, 2 Jul 2024 12:58:20 -0400 Subject: [PATCH 08/21] AUTHORS --- AUTHORS.rst | 4 +++- AUTHORS.txt | 9 --------- 2 files changed, 3 insertions(+), 10 deletions(-) delete mode 100644 AUTHORS.txt diff --git a/AUTHORS.rst b/AUTHORS.rst index 9f3f16dc..97e53c37 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -1,7 +1,9 @@ Authors ======= -Billinge Group and community contibutors. +Chris Farrow +Pavol Juhas +Simon J.L. Billinge Contributors ------------ diff --git a/AUTHORS.txt b/AUTHORS.txt deleted file mode 100644 index 2e7b1714..00000000 --- a/AUTHORS.txt +++ /dev/null @@ -1,9 +0,0 @@ -Authors: - -Chris Farrow -Pavol Juhas -Simon J.L. Billinge - -Contributors: - -https://github.com/diffpy/diffpy.srfit/graphs/contributors From cd9415b31d55ca551b21edec440850f045b57b40 Mon Sep 17 00:00:00 2001 From: Tieqiong Zhang Date: Tue, 2 Jul 2024 13:02:01 -0400 Subject: [PATCH 09/21] CHANGELOG --- CHANGELOG.md | 33 --------------------------------- CHANGELOG.rst | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 33 deletions(-) delete mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 7b90ae3f..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,33 +0,0 @@ -# Release notes - -## Version 3.0.0 – 2019-03-14 - -Differences from version 1.3. - -### Added - -- Support for Python 3.7, 3.6, 3.5 in addition to 2.7. - -### Changed - -- Always use lower-case imports from `diffpy.structure`. -- Use numeric-value sort to order variables in `PrintFitHook`. - -### Deprecated - -- Variable `__gitsha__` in the `version` module renamed to `__git_commit__`. - -### Removed - -- Optional upper and lower-bound arguments in `Parameter.setValue`. - The bounds can be set with `Parameter.boundRange` instead. -- Unused classes `ListOperator`, `SetOperator`. - -### Fixed - -- Metadata retrieval from `PDFContribution` hierarchy. -- Refresh `PDFGenerator` when its `rgrid` is changed in-place. -- Zero division in the `nppdfsas.py` example. -- Crash in `ellipsoidsas.py` example because of bug in `Parameter.setValue`. -- Pickling of `ProfileGenerator` objects and of bound class methods. -- Invalid escape sequences in string values. diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 26694512..5bc408da 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,3 +3,37 @@ Release Notes ============= .. current developments + + +Version 3.0.0 - 2019-03-14 +-------------------------- + +Differences from version 1.3. + +**Added** + +- Support for Python 3.7, 3.6, 3.5 in addition to 2.7. + +**Changed** + +- Always use lower-case imports from `diffpy.structure`. +- Use numeric-value sort to order variables in `PrintFitHook`. + +**Deprecated** + +- Variable `__gitsha__` in the `version` module renamed to `__git_commit__`. + +**Removed** + +- Optional upper and lower-bound arguments in `Parameter.setValue`. + The bounds can be set with `Parameter.boundRange` instead. +- Unused classes `ListOperator`, `SetOperator`. + +**Fixed** + +- Metadata retrieval from `PDFContribution` hierarchy. +- Refresh `PDFGenerator` when its `rgrid` is changed in-place. +- Zero division in the `nppdfsas.py` example. +- Crash in `ellipsoidsas.py` example because of bug in `Parameter.setValue`. +- Pickling of `ProfileGenerator` objects and of bound class methods. +- Invalid escape sequences in string values. From 8c6c57e1ca244c463bf6eb6c8ca596f551a99cfb Mon Sep 17 00:00:00 2001 From: Tieqiong Zhang Date: Tue, 2 Jul 2024 13:06:10 -0400 Subject: [PATCH 10/21] README --- README.rst | 168 +++++++++++++++++++++++++++-------------------------- 1 file changed, 85 insertions(+), 83 deletions(-) diff --git a/README.rst b/README.rst index 59fefa83..c8f313b9 100644 --- a/README.rst +++ b/README.rst @@ -1,14 +1,41 @@ -.. image:: https://travis-ci.org/diffpy/diffpy.srfit.svg?branch=master - :target: https://travis-ci.org/diffpy/diffpy.srfit +|Icon| |title|_ +=============== -.. image:: https://codecov.io/gh/diffpy/diffpy.srfit/branch/master/graph/badge.svg - :target: https://codecov.io/gh/diffpy/diffpy.srfit +.. |title| replace:: diffpy.srfit +.. _title: https://diffpy.github.io/diffpy.srfit +.. |Icon| image:: https://avatars.githubusercontent.com/diffpy + :target: https://diffpy.github.io/diffpy.srfit + :height: 100px -diffpy.srfit -======================================================================== +|PyPi| |Forge| |PythonVersion| |PR| -Configurable code for solving atomic structures. +|CI| |Codecov| |Black| |Tracking| + +.. |Black| image:: https://img.shields.io/badge/code_style-black-black + :target: https://github.com/psf/black + +.. |CI| image:: https://github.com/diffpy/diffpy.srfit/actions/workflows/main.yml/badge.svg + :target: https://github.com/diffpy/diffpy.srfit/actions/workflows/main.yml + +.. |Codecov| image:: https://codecov.io/gh/diffpy/diffpy.srfit/branch/main/graph/badge.svg + :target: https://codecov.io/gh/diffpy/diffpy.srfit + +.. |Forge| image:: https://img.shields.io/conda/vn/conda-forge/diffpy.srfit + :target: https://anaconda.org/conda-forge/diffpy.srfit + +.. |PR| image:: https://img.shields.io/badge/PR-Welcome-29ab47ff + +.. |PyPi| image:: https://img.shields.io/pypi/v/diffpy.srfit + :target: https://pypi.org/project/diffpy.srfit/ + +.. |PythonVersion| image:: https://img.shields.io/pypi/pyversions/diffpy.srfit + :target: https://pypi.org/project/diffpy.srfit/ + +.. |Tracking| image:: https://img.shields.io/badge/issue_tracking-github-blue + :target: https://github.com/diffpy/diffpy.srfit/issues + +SrFit - Structure refinement from diffraction data. Configurable code for solving atomic structures. The diffpy.srfit package provides the framework for building a global optimizer on the fly from components such as function calculators (that calculate @@ -32,115 +59,90 @@ obtain the total cost function. Additionally, diffpy.srfit is designed to be extensible, allowing the user to integrate external calculators to perform co-refinements with other techniques. -For more information about the diffpy.srfit library, see the users manual at -http://diffpy.github.io/diffpy.srfit. - -REQUIREMENTS ------------------------------------------------------------------------- - -The diffpy.srfit package requires Python 3.5 or later or 2.7 and -the following software: +For more information about the diffpy.srfit library, please consult our `online documentation `_. -* ``setuptools`` - software distribution tools for Python -* ``NumPy`` - numerical mathematics and fast array operations for Python -* ``SciPy`` - scientific libraries for Python -* ``matplotlib`` - python plotting library +Citation +-------- -Recommended software: +If you use diffpy.srfit in a scientific publication, we would like you to cite this package as -Optimizations involving crystal structures or molecules require + diffpy.srfit Package, https://github.com/diffpy/diffpy.srfit -* ``diffpy.structure`` - crystal structure container and parsers, - https://github.com/diffpy/diffpy.structure -* ``pyobjcryst`` - Crystal and Molecule storage, rigid units, bond - length and bond angle restraints, https://github.com/diffpy/pyobjcryst +Installation +------------ -Optimizations involving pair distribution functions PDF or bond valence -sums require +The preferred method is to use `Miniconda Python +`_ +and install from the "conda-forge" channel of Conda packages. -* ``diffpy.srreal`` - python library for PDF calculation, - https://github.com/diffpy/diffpy.srreal +To add "conda-forge" to the conda channels, run the following in a terminal. :: -Optimizations involving small angle scattering or shape characteristic -functions from the diffpy.srfit.sas module require + conda config --add channels conda-forge -* ``sas`` - module for calculation of P(R) in small-angle scattering - from the SasView project, http://www.sasview.org +We want to install our packages in a suitable conda environment. +The following creates and activates a new environment named ``diffpy.srfit_env`` :: -We recommend to use `Anaconda Python `_ -as it allows to install all software dependencies together with -diffpy.srfit. For other Python distributions it is necessary to -install the required software separately. As an example, on Ubuntu -Linux some of the required software can be installed using :: + conda create -n diffpy.srfit_env python=3 + conda activate diffpy.srfit_env - sudo apt-get install \ - python3-setuptools python3-numpy python3-scipy python3-matplotlib +Then, to fully install ``diffpy.srfit`` in our active environment, run :: -For other required packages see their respective web pages for installation -instructions. + conda install diffpy.srfit +Another option is to use ``pip`` to download and install the latest release from +`Python Package Index `_. +To install using ``pip`` into your ``diffpy.srfit_env`` environment, we will also have to install dependencies :: -INSTALLATION ------------------------------------------------------------------------- + pip install -r https://raw.githubusercontent.com/diffpy/diffpy.srfit/main/requirements/run.txt -The preferred method is to use Anaconda Python and install from the -"diffpy" channel of Anaconda packages :: +and then install the package :: - conda config --add channels diffpy - conda install diffpy.srfit + pip install diffpy.srfit -diffpy.srfit is also included in the "diffpy-cmi" collection -of packages for structure analysis :: +If you prefer to install from sources, after installing the dependencies, obtain the source archive from +`GitHub `_. Once installed, ``cd`` into your ``diffpy.srfit`` directory +and run the following :: - conda install diffpy-cmi + pip install . -Another option is to use ``easy_install`` to download and install the -latest release from `Python Package Index `_ :: +Support and Contribute +---------------------- - easy_install diffpy.srfit +`Diffpy user group `_ is the discussion forum for general questions and discussions about the use of diffpy.srfit. Please join the diffpy.srfit users community by joining the Google group. The diffpy.srfit project welcomes your expertise and enthusiasm! -If you prefer to install from sources, make sure all required software -packages are in place and then run :: +If you see a bug or want to request a feature, please `report it as an issue `_ and/or `submit a fix as a PR `_. You can also post it to the `Diffpy user group `_. - python setup.py install +Feel free to fork the project and contribute. To install diffpy.srfit +in a development mode, with its sources being directly used by Python +rather than copied to a package directory, use the following in the root +directory :: -You may need to use ``sudo`` with system Python so the process is -allowed to put files to the system directories. If administrator (root) -access is not available, consult the output from -``python setup.py install --help`` for options to install to a -user-writable locations. The installation integrity can be verified by -changing to the HOME directory and running :: + pip install -e . - python -m diffpy.srfit.tests.run +To ensure code quality and to prevent accidental commits into the default branch, please set up the use of our pre-commit +hooks. +1. Install pre-commit in your working environment by running ``conda install pre-commit``. -DEVELOPMENT ------------------------------------------------------------------------- +2. Initialize pre-commit (one time only) ``pre-commit install``. -diffpy.srfit is an open-source software developed as a part of the DiffPy-CMI -complex modeling initiative at the Brookhaven National Laboratory. The -diffpy.srfit sources are hosted at -https://github.com/diffpy/diffpy.srfit. +Thereafter your code will be linted by black and isort and checked against flake8 before you can commit. +If it fails by black or isort, just rerun and it should pass (black and isort will modify the files so should +pass after they are modified). If the flake8 test fails please see the error messages and fix them manually before +trying to commit again. -Feel free to fork the project and contribute. To install diffpy.srfit -in a development mode, with its sources being directly used by Python -rather than copied to a package directory, use :: +Improvements and fixes are always appreciated. - python setup.py develop --user +Before contribuing, please read our `Code of Conduct `_. -ACKNOWLEDGEMENT +Acknowledgements ------------------------------------------------------------------------ The source code in *observable.py* was derived from the 1.0 version of the Caltech "Pyre" project. +Contact +------- -CONTACTS ------------------------------------------------------------------------- - -For more information on diffpy.srfit please visit the project web-page - -http://www.diffpy.org - -or email Prof. Simon Billinge at sb2896@columbia.edu. +For more information on diffpy.srfit please visit the project `web-page `_ or email Prof. Simon Billinge at sb2896@columbia.edu. From c96d8b4a9561d0ae0d8258395a3888412f92595b Mon Sep 17 00:00:00 2001 From: Tieqiong Zhang Date: Tue, 2 Jul 2024 13:06:38 -0400 Subject: [PATCH 11/21] Use new Makefile --- doc/Makefile | 222 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 191 insertions(+), 31 deletions(-) diff --git a/doc/Makefile b/doc/Makefile index b9c30f1e..3720ec8e 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,34 +1,194 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build +BASENAME = $(subst .,,$(subst $() $(),,diffpy.srfit)) + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" -all: doc examples upload - -RELEASE = alpha9 -TARGET = farrowch@login.cacr.caltech.edu -DOCROOT = ~/docroot/diffraction/ -PKGROOT = ~/dev_danse_us/ - -.PHONY : doc -doc: - epydoc diffpy.srfit --html -vvv -o diffpy.srfitapi -n diffpy.srfit \ ---include-log --exclude diffpy.srfit.structure.cctbxstructure $@ - $(MAKE) -C devmanual $@ - -.PHONY : upload -upload: - rsync -ruvz --delete diffpy.srfitapi $(TARGET):$(DOCROOT) - ssh $(TARGET) "rm -rf $(DOCROOT)/diffpy.srfitapi-$(RELEASE)" - ssh $(TARGET) "cp -r $(DOCROOT)/diffpy.srfitapi $(DOCROOT)/diffpy.srfitapi-$(RELEASE)" - rsync -ruv srfit_examples.zip $(TARGET):$(PKGROOT) - ssh $(TARGET) "rm -rf $(PKGROOT)/srfit_examples-$(RELEASE).zip" - ssh $(TARGET) "cp -r $(PKGROOT)/srfit_examples.zip $(PKGROOT)/srfit_examples-$(RELEASE).zip" - $(MAKE) -C devmanual $@ - -.PHONY : examples -examples: - zip -r srfit_examples.zip ./examples/*.py ./examples/data -x \*svn\* -x \*threedoublepeaks\* -x \*temp\* -x \*test\* - -.PHONY : clean clean: - rm -rf diffpy.srfitapi - rm -f srfit_examples.zip - $(MAKE) -C devmanual $@ + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/$(BASENAME).qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/$(BASENAME).qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/$(BASENAME)" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/$(BASENAME)" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +# Manual publishing to the gh-pages branch + +GITREPOPATH = $(shell cd $(CURDIR) && git rev-parse --git-dir) +GITREMOTE = origin +GITREMOTEURL = $(shell git config --get remote.$(GITREMOTE).url) +GITLASTCOMMIT = $(shell git rev-parse --short HEAD) +publish: + @test -d build/html || \ + ( echo >&2 "Run 'make html' first!"; false ) + git show-ref --verify --quiet refs/heads/gh-pages || \ + git branch --track gh-pages $(GITREMOTE)/gh-pages + test -d build/gh-pages || \ + git clone -s -b gh-pages $(GITREPOPATH) build/gh-pages + cd build/gh-pages && \ + git pull $(GITREMOTEURL) gh-pages + rsync -acv --delete --exclude=.git --exclude=.rsync-exclude \ + --exclude-from=build/gh-pages/.rsync-exclude \ + --link-dest=$(CURDIR)/build/html build/html/ build/gh-pages/ + cd build/gh-pages && \ + git add --all . && \ + git diff --cached --quiet || \ + git commit -m "Sync with the source at $(GITLASTCOMMIT)." + cd build/gh-pages && \ + git push origin gh-pages From 40c1de1ce0849899020702f4442db726b51b311c Mon Sep 17 00:00:00 2001 From: Tieqiong Zhang Date: Tue, 2 Jul 2024 13:13:38 -0400 Subject: [PATCH 12/21] diffpy/__init__, srfit/__init__, tests/debug, run --- src/diffpy/__init__.py | 22 +++++++++--------- src/diffpy/srfit/__init__.py | 37 +++++++++--------------------- src/diffpy/srfit/tests/debug.py | 20 +++++++++-------- src/diffpy/srfit/tests/run.py | 40 ++++++++++++++++----------------- 4 files changed, 52 insertions(+), 67 deletions(-) diff --git a/src/diffpy/__init__.py b/src/diffpy/__init__.py index 11098213..08edc76b 100644 --- a/src/diffpy/__init__.py +++ b/src/diffpy/__init__.py @@ -1,26 +1,24 @@ #!/usr/bin/env python ############################################################################## # -# diffpy by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2008 The Trustees of Columbia University -# in the City of New York. All rights reserved. +# (c) 2024 The Trustees of Columbia University in the City of New York. +# All rights reserved. # -# File coded by: Chris Farrow +# File coded by: Billinge Group members and community contributors. # -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE_DANSE.txt for license information. +# See GitHub contributions for a more detailed list of contributors. +# https://github.com/diffpy/diffpy.srfit/graphs/contributors +# +# See LICENSE.rst for license information. # ############################################################################## -"""diffpy - tools for structure analysis by diffraction. - -Blank namespace package. -""" +"""Blank namespace package for module diffpy.""" from pkgutil import extend_path -__path__ = extend_path(__path__, __name__) +__path__ = extend_path(__path__, __name__) # End of file + diff --git a/src/diffpy/srfit/__init__.py b/src/diffpy/srfit/__init__.py index 76d70de4..8a0d9cfa 100644 --- a/src/diffpy/srfit/__init__.py +++ b/src/diffpy/srfit/__init__.py @@ -1,39 +1,24 @@ #!/usr/bin/env python ############################################################################## # -# diffpy.srfit by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2008 The Trustees of Columbia University -# in the City of New York. All rights reserved. +# (c) 2024 The Trustees of Columbia University in the City of New York. +# All rights reserved. # -# File coded by: Chris Farrow +# File coded by: Billinge Group members and community contributors. # -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE_DANSE.txt for license information. +# See GitHub contributions for a more detailed list of contributors. +# https://github.com/diffpy/diffpy.srfit/graphs/contributors +# +# See LICENSE.rst for license information. # ############################################################################## -"""Complex modeling framework for structure refinement and solution. - -SrFit is a tool for coherently combining known information about a material to -derive other properties, in particular material structure. SrFit allows the -customization and creation of structure representations, profile calculators, -constraints, restraints and file input parsers. The customized pieces can be -glued together within SrFit to optimize a structure, or other physically -relevant information from one or more experimental profiles. Other known -information about the system of interest can be included with arbitrarily -complex constraints and restraints. In this way, the end user creates a -customized fitting application that suits the problem to the available -information. - -The subpackages herein define various pieces of the SrFit framework. Developers -are encouraged to work through the examples described in the documentation to -learn how to use and customize the various parts of SrFit. -""" - -__all__ = ["__version__"] +"""SrFit - Structure refinement from diffraction data""" # package version from diffpy.srfit.version import __version__ +# silence the pyflakes syntax checker +assert __version__ or True + # End of file diff --git a/src/diffpy/srfit/tests/debug.py b/src/diffpy/srfit/tests/debug.py index a71ff378..f7320d21 100644 --- a/src/diffpy/srfit/tests/debug.py +++ b/src/diffpy/srfit/tests/debug.py @@ -1,15 +1,15 @@ #!/usr/bin/env python ############################################################################## # -# diffpy.srfit Complex Modeling Initiative -# (c) 2016 Brookhaven Science Associates, -# Brookhaven National Laboratory. -# All rights reserved. +# (c) 2024 The Trustees of Columbia University in the City of New York. +# All rights reserved. # -# File coded by: Pavol Juhas +# File coded by: Billinge Group members and community contributors. # -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. +# See GitHub contributions for a more detailed list of contributors. +# https://github.com/diffpy/diffpy.srfit/graphs/contributors +# +# See LICENSE.rst for license information. # ############################################################################## @@ -22,10 +22,12 @@ """ -if __name__ == '__main__': +if __name__ == "__main__": import sys + from diffpy.srfit.tests import testsuite - pattern = sys.argv[1] if len(sys.argv) > 1 else '' + + pattern = sys.argv[1] if len(sys.argv) > 1 else "" suite = testsuite(pattern) suite.debug() diff --git a/src/diffpy/srfit/tests/run.py b/src/diffpy/srfit/tests/run.py index f1c83fa0..eeb0a0b0 100644 --- a/src/diffpy/srfit/tests/run.py +++ b/src/diffpy/srfit/tests/run.py @@ -1,34 +1,34 @@ #!/usr/bin/env python ############################################################################## # -# diffpy.srfit by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2010 The Trustees of Columbia University -# in the City of New York. All rights reserved. +# (c) 2024 The Trustees of Columbia University in the City of New York. +# All rights reserved. # -# File coded by: Pavol Juhas +# File coded by: Billinge Group members and community contributors. # -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE_DANSE.txt for license information. +# See GitHub contributions for a more detailed list of contributors. +# https://github.com/diffpy/diffpy.srfit/graphs/contributors +# +# See LICENSE.rst for license information. # ############################################################################## - """Convenience module for executing all unit tests with - python -m diffpy.srfit.tests.run """ +import sys + +import pytest -if __name__ == '__main__': - import sys - # show warnings by default - if not sys.warnoptions: - import os, warnings - warnings.simplefilter("default") - # also affect subprocesses - os.environ["PYTHONWARNINGS"] = "default" - from diffpy.srfit.tests import test - # produce zero exit code for a successful test - sys.exit(not test().wasSuccessful()) +if __name__ == "__main__": + # show output results from every test function + args = ["-v"] + # show the message output for skipped and expected failure tests + if len(sys.argv) > 1: + args.extend(sys.argv[1:]) + print("pytest arguments: {}".format(args)) + # call pytest and exit with the return code from pytest + exit_res = pytest.main(args) + sys.exit(exit_res) # End of file From 85530cc057615d7f5aa5edb7193562c55e09b230 Mon Sep 17 00:00:00 2001 From: Tieqiong Zhang Date: Tue, 2 Jul 2024 13:15:10 -0400 Subject: [PATCH 13/21] Use new srfit/version --- src/diffpy/srfit/version.py | 55 +++++++++---------------------------- 1 file changed, 13 insertions(+), 42 deletions(-) diff --git a/src/diffpy/srfit/version.py b/src/diffpy/srfit/version.py index 98c20188..e8d23296 100644 --- a/src/diffpy/srfit/version.py +++ b/src/diffpy/srfit/version.py @@ -1,55 +1,26 @@ #!/usr/bin/env python ############################################################################## # -# diffpy.srfit by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2008 The Trustees of Columbia University -# in the City of New York. All rights reserved. +# (c) 2024 The Trustees of Columbia University in the City of New York. +# All rights reserved. # -# File coded by: Chris Farrow +# File coded by: Billinge Group members and community contributors. # -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE_DANSE.txt for license information. +# See GitHub contributions for a more detailed list of contributors. +# https://github.com/diffpy/diffpy.srfit/graphs/contributors +# +# See LICENSE.rst for license information. # ############################################################################## -""" -Definition of __version__, __date__, __timestamp__, __git_commit__. - -Notes ------ -Variable `__gitsha__` is deprecated as of version 3.0. -Use `__git_commit__` instead. -""" - -__all__ = ['__date__', '__git_commit__', '__timestamp__', '__version__'] - -import os.path - -from pkg_resources import resource_filename - - -# obtain version information from the version.cfg file -cp = dict(version='', date='', commit='', timestamp='0') -fcfg = resource_filename(__name__, 'version.cfg') -if not os.path.isfile(fcfg): # pragma: no cover - from warnings import warn - warn('Package metadata not found, execute "./setup.py egg_info".') - fcfg = os.devnull -with open(fcfg) as fp: - kwords = [[w.strip() for w in line.split(' = ', 1)] - for line in fp if line[:1].isalpha() and ' = ' in line] -assert all(w[0] in cp for w in kwords), "received unrecognized keyword" -cp.update(kwords) +"""Definition of __version__.""" -__version__ = cp['version'] -__date__ = cp['date'] -__git_commit__ = cp['commit'] -__timestamp__ = int(cp['timestamp']) +# We do not use the other three variables, but can be added back if needed. +# __all__ = ["__date__", "__git_commit__", "__timestamp__", "__version__"] -# TODO remove deprecated __gitsha__ in version 3.1. -__gitsha__ = __git_commit__ +# obtain version information +from importlib.metadata import version -del cp, fcfg, fp, kwords +__version__ = version("diffpy.srfit") # End of file From b6b6b29519a3091e06640b9cbfd95689a4ac27d0 Mon Sep 17 00:00:00 2001 From: Tieqiong Zhang Date: Tue, 2 Jul 2024 13:25:44 -0400 Subject: [PATCH 14/21] pyproject.toml, MANIFEST --- MANIFEST.in | 26 +++++++++--------- pyproject.toml | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 14 deletions(-) create mode 100644 pyproject.toml diff --git a/MANIFEST.in b/MANIFEST.in index 3894e104..db5bff22 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,16 +1,14 @@ -recursive-include src * -include AUTHORS.txt LICENSE*.txt README.rst -recursive-exclude src *.pyc -global-exclude .gitattributes .gitignore .gitarchive.cfg -global-exclude .DS_Store +include AUTHORS.rst +include LICENSE +include README.rst +include requirements.txt -# Avoid user content in setup.cfg to make distribution reproducible. -exclude setup.cfg +recursive-exclude * __pycache__ +recursive-exclude * *.py[co] -# Exclude git-tracked files spuriously added by setuptools_scm -exclude .codecov.yml -exclude .coveragerc -exclude .travis* -prune conda-recipe -prune devutils -prune doc +recursive-include docs *.rst conf.py Makefile make.bat + +include diffpy.srfit/version.py + +# If including data files in the package, add them like: +# include path/to/data_file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..71fc177c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,72 @@ +[build-system] +requires = ["setuptools>=62.0", "setuptools-git-versioning<2"] +build-backend = "setuptools.build_meta" + +[project] +name = "diffpy.srfit" +dynamic=['version'] +authors = [ + { name="Simon J.L. Billinge group", email="simon.billinge@gmail.com" }, +] +maintainers = [ + { name="Simon J.L. Billinge group", email="simon.billinge@gmail.com" }, +] +description = "SrFit - Structure refinement from diffraction data" +keywords = ['diffpy', 'optimization', 'constraints', 'restraints', 'structure refinement', 'complex modeling'] +readme = "README.rst" +requires-python = ">=3.10" +classifiers = [ + 'Development Status :: 5 - Production/Stable', + 'Environment :: Console', + 'Intended Audience :: Developers', + 'Intended Audience :: Science/Research', + 'License :: OSI Approved :: BSD License', + 'Operating System :: MacOS :: MacOS X', + 'Operating System :: Microsoft :: Windows', + 'Operating System :: POSIX', + 'Operating System :: Unix', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12', + 'Topic :: Scientific/Engineering :: Physics', + 'Topic :: Scientific/Engineering :: Chemistry', +] + +[project.urls] +Homepage = "https://github.com/diffpy/diffpy.srfit/" +Issues = "https://github.com/diffpy/diffpy.srfit/issues/" + +[tool.setuptools-git-versioning] +enabled = true +template = "{tag}" +dev_template = "{tag}" +dirty_template = "{tag}" + +[tool.setuptools.packages.find] +where = ["src"] # list of folders that contain the packages (["."] by default) +include = ["*"] # package names should match these glob patterns (["*"] by default) +exclude = ["diffpy.srfit.tests*"] # exclude packages matching these glob patterns (empty by default) +namespaces = false # to disable scanning PEP 420 namespaces (true by default) + +[tool.black] +line-length = 115 +include = '\.pyi?$' +exclude = ''' +/( + \.git + | \.hg + | \.mypy_cache + | \.tox + | \.venv + | \.rst + | \.txt + | _build + | buck-out + | build + | dist + + # The following are specific to Black, you probably don't want those. + | blib2to3 + | tests/data +)/ +''' From 6d43cc6730d95771a7feb578bebb1ba6fb86c104 Mon Sep 17 00:00:00 2001 From: Tieqiong Zhang Date: Tue, 2 Jul 2024 13:28:46 -0400 Subject: [PATCH 15/21] Use new BSD license --- LICENSE.rst | 30 ++++++++++ LICENSE.txt | 137 ---------------------------------------------- LICENSE_DANSE.txt | 34 ------------ 3 files changed, 30 insertions(+), 171 deletions(-) create mode 100644 LICENSE.rst delete mode 100644 LICENSE.txt delete mode 100644 LICENSE_DANSE.txt diff --git a/LICENSE.rst b/LICENSE.rst new file mode 100644 index 00000000..95a04ac9 --- /dev/null +++ b/LICENSE.rst @@ -0,0 +1,30 @@ +BSD 3-Clause License + +Copyright (c) 2024, The Trustees of Columbia University +in the City of New York. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index f6d92af7..00000000 --- a/LICENSE.txt +++ /dev/null @@ -1,137 +0,0 @@ -OPEN SOURCE LICENSE AGREEMENT -============================= - -Copyright (c) 2009-2011, University of Tennessee -Copyright (c) 1989, 1991 Free Software Foundation, Inc. -Copyright (c) 2006, The Regents of the University of California through - Lawrence Berkeley National Laboratory -Copyright (c) 2014, Australian Synchrotron Research Program Inc., ("ASRP") -Copyright (c) 2006-2007, Board of Trustees of Michigan State University -Copyright (c) 2008-2012, The Trustees of Columbia University in the City - of New York - -Copyright (c) 2014-2019, Brookhaven Science Associates, Brookhaven National - Laboratory - - -The "DiffPy-CMI" is distributed subject to the following license conditions: - - -SOFTWARE LICENSE AGREEMENT - - Software: DiffPy-CMI - - -(1) The "Software", below, refers to the aforementioned DiffPy-CMI (in either -source code, or binary form and accompanying documentation). - -Part of the software was derived from the DANSE, ObjCryst++ (with permission), -PyCifRW, Python periodictable, CCTBX, and SasView open source projects, of -which the original Copyrights are contained in each individual file. - -Each licensee is addressed as "you" or "Licensee." - - -(2) The copyright holders shown above and their third-party Licensors hereby -grant licensee a royalty-free nonexclusive license, subject to the limitations -stated herein and U.S. Government license rights. - - -(3) You may modify and make a copy or copies of the software for use within -your organization, if you meet the following conditions: - - (a) Copies in source code must include the copyright notice and this - software license agreement. - - (b) Copies in binary form must include the copyright notice and this - Software License Agreement in the documentation and/or other materials - provided with the copy. - - -(4) You may modify a copy or copies of the Software or any portion of it, thus -forming a work based on the Software, and distribute copies of such work -outside your organization, if you meet all of the following conditions: - - (a) Copies in source code must include the copyright notice and this - Software License Agreement; - - (b) Copies in binary form must include the copyright notice and this - Software License Agreement in the documentation and/or other materials - provided with the copy; - - (c) Modified copies and works based on the Software must carry prominent - notices stating that you changed specified portions of the Software. - - (d) Neither the name of Brookhaven Science Associates or Brookhaven - National Laboratory nor the names of its contributors may be used to - endorse or promote products derived from this software without specific - written permission. - - -(5) Portions of the Software resulted from work developed under a U.S. -Government contract and are subject to the following license: -The Government is granted for itself and others acting on its behalf a -paid-up, nonexclusive, irrevocable worldwide license in this computer software -to reproduce, prepare derivative works, and perform publicly and display -publicly. - - -(6) WARRANTY DISCLAIMER. THE SOFTWARE IS SUPPLIED "AS IS" WITHOUT -WARRANTY OF ANY KIND. THE COPYRIGHT HOLDERS, THEIR THIRD PARTY -LICENSORS, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF ENERGY, AND -THEIR EMPLOYEES: (1) DISCLAIM ANY WARRANTIES, EXPRESS OR IMPLIED, INCLUDING -BUT NOT LIMITED TO ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE, TITLE OR NON-INFRINGEMENT, (2) DO NOT ASSUME ANY LEGAL -LIABILITY OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR USEFULNESS OF -THE SOFTWARE, (3) DO NOT REPRESENT THAT USE OF THE SOFTWARE WOULD NOT INFRINGE -PRIVATELY OWNED RIGHTS, (4) DO NOT WARRANT THAT THE SOFTWARE WILL FUNCTION -UNINTERRUPTED, THAT IT IS ERROR-FREE OR THAT ANY ERRORS WILL BE CORRECTED. - - -(7) LIMITATION OF LIABILITY. IN NO EVENT WILL THE COPYRIGHT HOLDERS, THEIR -THIRD PARTY LICENSORS, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF -ENERGY, OR THEIR EMPLOYEES: BE LIABLE FOR ANY INDIRECT, INCIDENTAL, -CONSEQUENTIAL, SPECIAL OR PUNITIVE DAMAGES OF ANY KIND OR NATURE, INCLUDING -BUT NOT LIMITED TO LOSS OF PROFITS OR LOSS OF DATA, FOR ANY REASON WHATSOEVER, -WHETHER SUCH LIABILITY IS ASSERTED ON THE BASIS OF CONTRACT, TORT (INCLUDING -NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE, EVEN IF ANY OF SAID PARTIES HAS -BEEN WARNED OF THE POSSIBILITY OF SUCH LOSS OR DAMAGES. - - -Brookhaven National Laboratory Notice -===================================== - -Acknowledgment of sponsorship ------------------------------ - -This software was produced by the Brookhaven National Laboratory, under -Contract DE-AC02-98CH10886 with the Department of Energy. - - -Government disclaimer of liability ----------------------------------- - -Neither the United States nor the United States Department of Energy, nor -any of their employees, makes any warranty, express or implied, or assumes -any legal liability or responsibility for the accuracy, completeness, or -usefulness of any data, apparatus, product, or process disclosed, or -represents that its use would not infringe privately owned rights. - - -Brookhaven disclaimer of liability ----------------------------------- - -Brookhaven National Laboratory makes no representations or warranties, -express or implied, nor assumes any liability for the use of this software. - - -Maintenance of notice ---------------------- - -In the interest of clarity regarding the origin and status of this -software, Brookhaven National Laboratory requests that any recipient of it -maintain this notice affixed to any distribution by the recipient that -contains a copy or derivative of this software. - - -END OF LICENSE diff --git a/LICENSE_DANSE.txt b/LICENSE_DANSE.txt deleted file mode 100644 index c92ca2d5..00000000 --- a/LICENSE_DANSE.txt +++ /dev/null @@ -1,34 +0,0 @@ -This program is part of the DiffPy and DANSE open-source projects at Columbia -University and is available subject to the conditions and terms laid out below. - -Copyright (c) 2008-2011, The Trustees of Columbia University in -the City of New York. All rights reserved. - -For more information please visit the diffpy web-page at - http://www.diffpy.org -or email Prof. Simon Billinge at sb2896@columbia.edu. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the names of COLUMBIA UNIVERSITY, MICHIGAN STATE UNIVERSITY nor the - names of their contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. From defa1a81e12f60422a3b18df2b5408f907443927 Mon Sep 17 00:00:00 2001 From: Tieqiong Zhang Date: Tue, 2 Jul 2024 13:36:13 -0400 Subject: [PATCH 16/21] autodoc_mock_imports --- doc/source/conf.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/source/conf.py b/doc/source/conf.py index e7654b23..8c938625 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -18,6 +18,8 @@ from importlib.metadata import version from pathlib import Path +autodoc_mock_imports = ["scipy", "pyobjcryst"] + # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use Path().resolve() to make it absolute, like shown here. From 517c416127a5bbcbda34bd315477180a5ea6b744 Mon Sep 17 00:00:00 2001 From: Tieqiong Zhang Date: Tue, 2 Jul 2024 16:11:18 -0400 Subject: [PATCH 17/21] add cookierelease to CHANGELOG --- CHANGELOG.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 5bc408da..288184ff 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,21 @@ Release Notes .. current developments +Version 3.1.0 - 2024-7-2 + +**Added:** + +**Changed:** + +**Deprecated:** + +**Removed:** + +**Fixed:** + +- Repo structure modified to the new diffpy standard + +**Security:** Version 3.0.0 - 2019-03-14 -------------------------- From 7ca347cb2874fb2e1290fd4257b3cc2c15dd73e3 Mon Sep 17 00:00:00 2001 From: Tieqiong Zhang Date: Tue, 2 Jul 2024 16:11:43 -0400 Subject: [PATCH 18/21] modified: doc/source/index.rst --- doc/source/index.rst | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/doc/source/index.rst b/doc/source/index.rst index 69a7994b..0e2dc31f 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -1,3 +1,5 @@ +.. _developers-guide-index: + ####### |title| ####### @@ -9,12 +11,38 @@ diffpy.srfit - SrFit - Structure refinement from diffraction data. | Software version |release|. | Last updated |today|. +The diffpy.srfit package provides the framework for building a global optimizer +on the fly from components such as function calculators (that calculate +different data spectra), regression algorithms and structure models. The +software is capable of co-refinement using multiple information sources or +models. It provides a uniform interface for various regression algorithms. The +target function being optimized can be specified by the user according to the +data available. + +Within the diffpy.srfit framework, any parameter used in describing the +structure of a material can be passed as a refinable variable to the global +optimizer. Once parameters are declared as variables they can easily be turned +"on" or "off", i.e. fixed or allowed to vary. Additionally, variables may be +constrained to obey mathematical relationships with other parameters or +variables used in the structural model. Restraints can be applied to +variables, which adds a penalty to the refinement process commensurate with the +deviation from the known value or range. The cost function can also be +customized by the user. If the refinement contains multiple models, each model +can have its own cost function which will be properly weighted and combined to +obtain the total cost function. Additionally, diffpy.srfit is designed to be +extensible, allowing the user to integrate external calculators to perform +co-refinements with other techniques. + ======= Authors ======= -diffpy.srfit is developed by Billinge Group -and its community contributors. +diffpy.srfit is developed by members of the Billinge Group at +Columbia University and at Brookhaven National Laboratory including +Christopher L. Farrow, Pavol Juhás, Simon J.L. Billinge. + +The source code in *observable.py* was derived from the 1.0 version +of the Caltech "Pyre" project. For a detailed list of contributors see https://github.com/diffpy/diffpy.srfit/graphs/contributors. @@ -26,6 +54,16 @@ Installation See the `README `_ file included with the distribution. +=========== +Where next? +=========== + +.. toctree:: + :maxdepth: 2 + + examples.rst + extending.rst + ================= Table of contents ================= @@ -41,4 +79,5 @@ Indices ======= * :ref:`genindex` +* :ref:`modindex` * :ref:`search` From 46943fcf3cf693d07c81b925f82f1fdd92e3c102 Mon Sep 17 00:00:00 2001 From: Tieqiong Zhang Date: Tue, 2 Jul 2024 16:13:21 -0400 Subject: [PATCH 19/21] New API with updated index --- .../api/diffpy.srfit.equation.literals.rst | 31 +++--- doc/source/api/diffpy.srfit.equation.rst | 22 ++-- .../api/diffpy.srfit.equation.visitors.rst | 37 +++---- .../api/diffpy.srfit.example_package.rst | 31 ------ doc/source/api/diffpy.srfit.fitbase.rst | 103 +++++++++--------- doc/source/api/diffpy.srfit.interface.rst | 17 ++- doc/source/api/diffpy.srfit.pdf.rst | 45 ++++---- doc/source/api/diffpy.srfit.rst | 25 +++-- doc/source/api/diffpy.srfit.sas.rst | 45 ++++---- doc/source/api/diffpy.srfit.structure.rst | 53 +++++---- doc/source/api/diffpy.srfit.util.rst | 41 ++++--- 11 files changed, 220 insertions(+), 230 deletions(-) delete mode 100644 doc/source/api/diffpy.srfit.example_package.rst diff --git a/doc/source/api/diffpy.srfit.equation.literals.rst b/doc/source/api/diffpy.srfit.equation.literals.rst index 35b905b1..6875b5ef 100644 --- a/doc/source/api/diffpy.srfit.equation.literals.rst +++ b/doc/source/api/diffpy.srfit.equation.literals.rst @@ -1,27 +1,34 @@ +:tocdepth: -1 + diffpy.srfit.equation.literals package ====================================== +.. automodule:: diffpy.srfit.equation.literals + :members: + :undoc-members: + :show-inheritance: + Submodules ---------- -diffpy.srfit.equation.literals.abcs module ------------------------------------------- +diffpy.srfit.equation.literals.argument module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.equation.literals.abcs +.. automodule:: diffpy.srfit.equation.literals.argument :members: :undoc-members: :show-inheritance: -diffpy.srfit.equation.literals.argument module ----------------------------------------------- +diffpy.srfit.equation.literals.abcs module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.equation.literals.argument +.. automodule:: diffpy.srfit.equation.literals.abcs :members: :undoc-members: :show-inheritance: diffpy.srfit.equation.literals.literal module ---------------------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. automodule:: diffpy.srfit.equation.literals.literal :members: @@ -29,18 +36,10 @@ diffpy.srfit.equation.literals.literal module :show-inheritance: diffpy.srfit.equation.literals.operators module ------------------------------------------------ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. automodule:: diffpy.srfit.equation.literals.operators :members: :undoc-members: :show-inheritance: - -Module contents ---------------- - -.. automodule:: diffpy.srfit.equation.literals - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/source/api/diffpy.srfit.equation.rst b/doc/source/api/diffpy.srfit.equation.rst index f5642da1..f7a47192 100644 --- a/doc/source/api/diffpy.srfit.equation.rst +++ b/doc/source/api/diffpy.srfit.equation.rst @@ -1,19 +1,27 @@ +:tocdepth: -1 + diffpy.srfit.equation package ============================= +.. automodule:: diffpy.srfit.equation + :members: + :undoc-members: + :show-inheritance: + Subpackages ----------- .. toctree:: + :titlesonly: - diffpy.srfit.equation.literals diffpy.srfit.equation.visitors + diffpy.srfit.equation.literals Submodules ---------- diffpy.srfit.equation.builder module ------------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. automodule:: diffpy.srfit.equation.builder :members: @@ -21,18 +29,10 @@ diffpy.srfit.equation.builder module :show-inheritance: diffpy.srfit.equation.equationmod module ----------------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. automodule:: diffpy.srfit.equation.equationmod :members: :undoc-members: :show-inheritance: - -Module contents ---------------- - -.. automodule:: diffpy.srfit.equation - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/source/api/diffpy.srfit.equation.visitors.rst b/doc/source/api/diffpy.srfit.equation.visitors.rst index de17f93d..54e10bc6 100644 --- a/doc/source/api/diffpy.srfit.equation.visitors.rst +++ b/doc/source/api/diffpy.srfit.equation.visitors.rst @@ -1,54 +1,53 @@ +:tocdepth: -1 + diffpy.srfit.equation.visitors package ====================================== -Submodules ----------- - -diffpy.srfit.equation.visitors.argfinder module ------------------------------------------------ - -.. automodule:: diffpy.srfit.equation.visitors.argfinder +.. automodule:: diffpy.srfit.equation.visitors :members: :undoc-members: :show-inheritance: -diffpy.srfit.equation.visitors.printer module ---------------------------------------------- +Submodules +---------- -.. automodule:: diffpy.srfit.equation.visitors.printer +diffpy.srfit.equation.visitors.validator module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: diffpy.srfit.equation.visitors.validator :members: :undoc-members: :show-inheritance: diffpy.srfit.equation.visitors.swapper module ---------------------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. automodule:: diffpy.srfit.equation.visitors.swapper :members: :undoc-members: :show-inheritance: -diffpy.srfit.equation.visitors.validator module ------------------------------------------------ +diffpy.srfit.equation.visitors.argfinder module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.equation.visitors.validator +.. automodule:: diffpy.srfit.equation.visitors.argfinder :members: :undoc-members: :show-inheritance: diffpy.srfit.equation.visitors.visitor module ---------------------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. automodule:: diffpy.srfit.equation.visitors.visitor :members: :undoc-members: :show-inheritance: +diffpy.srfit.equation.visitors.printer module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Module contents ---------------- - -.. automodule:: diffpy.srfit.equation.visitors +.. automodule:: diffpy.srfit.equation.visitors.printer :members: :undoc-members: :show-inheritance: + diff --git a/doc/source/api/diffpy.srfit.example_package.rst b/doc/source/api/diffpy.srfit.example_package.rst deleted file mode 100644 index 60910070..00000000 --- a/doc/source/api/diffpy.srfit.example_package.rst +++ /dev/null @@ -1,31 +0,0 @@ -.. _example_package documentation: - -|title| -======= - -.. |title| replace:: diffpy.srfit.example_package package - -.. automodule:: diffpy.srfit.example_package - :members: - :undoc-members: - :show-inheritance: - -|foo| ------ - -.. |foo| replace:: diffpy.srfit.example_package.foo module - -.. automodule:: diffpy.srfit.example_package.foo - :members: - :undoc-members: - :show-inheritance: - -|bar| ------ - -.. |bar| replace:: diffpy.srfit.example_package.bar module - -.. automodule:: diffpy.srfit.example_package.foo - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/source/api/diffpy.srfit.fitbase.rst b/doc/source/api/diffpy.srfit.fitbase.rst index 44093442..5c092c9f 100644 --- a/doc/source/api/diffpy.srfit.fitbase.rst +++ b/doc/source/api/diffpy.srfit.fitbase.rst @@ -1,142 +1,141 @@ +:tocdepth: -1 + diffpy.srfit.fitbase package ============================ -Submodules ----------- - -diffpy.srfit.fitbase.calculator module --------------------------------------- - -.. automodule:: diffpy.srfit.fitbase.calculator +.. automodule:: diffpy.srfit.fitbase :members: :undoc-members: :show-inheritance: -diffpy.srfit.fitbase.configurable module ----------------------------------------- +Submodules +---------- -.. automodule:: diffpy.srfit.fitbase.configurable +diffpy.srfit.fitbase.simplerecipe module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: diffpy.srfit.fitbase.simplerecipe :members: :undoc-members: :show-inheritance: diffpy.srfit.fitbase.constraint module --------------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. automodule:: diffpy.srfit.fitbase.constraint :members: :undoc-members: :show-inheritance: -diffpy.srfit.fitbase.fitcontribution module -------------------------------------------- - -.. automodule:: diffpy.srfit.fitbase.fitcontribution - :members: - :undoc-members: - :show-inheritance: - diffpy.srfit.fitbase.fithook module ------------------------------------ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. automodule:: diffpy.srfit.fitbase.fithook :members: :undoc-members: :show-inheritance: -diffpy.srfit.fitbase.fitrecipe module -------------------------------------- +diffpy.srfit.fitbase.fitresults module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.fitbase.fitrecipe +.. automodule:: diffpy.srfit.fitbase.fitresults :members: :undoc-members: :show-inheritance: -diffpy.srfit.fitbase.fitresults module --------------------------------------- +diffpy.srfit.fitbase.profilegenerator module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.fitbase.fitresults +.. automodule:: diffpy.srfit.fitbase.profilegenerator :members: :undoc-members: :show-inheritance: -diffpy.srfit.fitbase.parameter module -------------------------------------- +diffpy.srfit.fitbase.validatable module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.fitbase.parameter +.. automodule:: diffpy.srfit.fitbase.validatable :members: :undoc-members: :show-inheritance: -diffpy.srfit.fitbase.parameterset module ----------------------------------------- +diffpy.srfit.fitbase.configurable module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.fitbase.parameterset +.. automodule:: diffpy.srfit.fitbase.configurable :members: :undoc-members: :show-inheritance: diffpy.srfit.fitbase.profile module ------------------------------------ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. automodule:: diffpy.srfit.fitbase.profile :members: :undoc-members: :show-inheritance: -diffpy.srfit.fitbase.profilegenerator module --------------------------------------------- +diffpy.srfit.fitbase.restraint module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.fitbase.profilegenerator +.. automodule:: diffpy.srfit.fitbase.restraint :members: :undoc-members: :show-inheritance: -diffpy.srfit.fitbase.profileparser module ------------------------------------------ +diffpy.srfit.fitbase.fitcontribution module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.fitbase.profileparser +.. automodule:: diffpy.srfit.fitbase.fitcontribution :members: :undoc-members: :show-inheritance: diffpy.srfit.fitbase.recipeorganizer module -------------------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. automodule:: diffpy.srfit.fitbase.recipeorganizer :members: :undoc-members: :show-inheritance: -diffpy.srfit.fitbase.restraint module -------------------------------------- +diffpy.srfit.fitbase.fitrecipe module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.fitbase.restraint +.. automodule:: diffpy.srfit.fitbase.fitrecipe :members: :undoc-members: :show-inheritance: -diffpy.srfit.fitbase.simplerecipe module ----------------------------------------- +diffpy.srfit.fitbase.parameterset module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.fitbase.simplerecipe +.. automodule:: diffpy.srfit.fitbase.parameterset :members: :undoc-members: :show-inheritance: -diffpy.srfit.fitbase.validatable module ---------------------------------------- +diffpy.srfit.fitbase.calculator module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.fitbase.validatable +.. automodule:: diffpy.srfit.fitbase.calculator :members: :undoc-members: :show-inheritance: +diffpy.srfit.fitbase.parameter module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Module contents ---------------- +.. automodule:: diffpy.srfit.fitbase.parameter + :members: + :undoc-members: + :show-inheritance: -.. automodule:: diffpy.srfit.fitbase +diffpy.srfit.fitbase.profileparser module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: diffpy.srfit.fitbase.profileparser :members: :undoc-members: :show-inheritance: + diff --git a/doc/source/api/diffpy.srfit.interface.rst b/doc/source/api/diffpy.srfit.interface.rst index 4b6296a8..40b829d7 100644 --- a/doc/source/api/diffpy.srfit.interface.rst +++ b/doc/source/api/diffpy.srfit.interface.rst @@ -1,22 +1,21 @@ +:tocdepth: -1 + diffpy.srfit.interface package ============================== +.. automodule:: diffpy.srfit.interface + :members: + :undoc-members: + :show-inheritance: + Submodules ---------- diffpy.srfit.interface.interface module ---------------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. automodule:: diffpy.srfit.interface.interface :members: :undoc-members: :show-inheritance: - -Module contents ---------------- - -.. automodule:: diffpy.srfit.interface - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/source/api/diffpy.srfit.pdf.rst b/doc/source/api/diffpy.srfit.pdf.rst index a336a375..60f3e947 100644 --- a/doc/source/api/diffpy.srfit.pdf.rst +++ b/doc/source/api/diffpy.srfit.pdf.rst @@ -1,62 +1,61 @@ +:tocdepth: -1 + diffpy.srfit.pdf package ======================== +.. automodule:: diffpy.srfit.pdf + :members: + :undoc-members: + :show-inheritance: + Submodules ---------- -diffpy.srfit.pdf.basepdfgenerator module ----------------------------------------- +diffpy.srfit.pdf.debyepdfgenerator module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.pdf.basepdfgenerator +.. automodule:: diffpy.srfit.pdf.debyepdfgenerator :members: :undoc-members: :show-inheritance: diffpy.srfit.pdf.characteristicfunctions module ------------------------------------------------ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. automodule:: diffpy.srfit.pdf.characteristicfunctions :members: :undoc-members: :show-inheritance: -diffpy.srfit.pdf.debyepdfgenerator module ------------------------------------------ - -.. automodule:: diffpy.srfit.pdf.debyepdfgenerator - :members: - :undoc-members: - :show-inheritance: - -diffpy.srfit.pdf.pdfcontribution module ---------------------------------------- +diffpy.srfit.pdf.pdfparser module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.pdf.pdfcontribution +.. automodule:: diffpy.srfit.pdf.pdfparser :members: :undoc-members: :show-inheritance: diffpy.srfit.pdf.pdfgenerator module ------------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. automodule:: diffpy.srfit.pdf.pdfgenerator :members: :undoc-members: :show-inheritance: -diffpy.srfit.pdf.pdfparser module ---------------------------------- +diffpy.srfit.pdf.basepdfgenerator module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.pdf.pdfparser +.. automodule:: diffpy.srfit.pdf.basepdfgenerator :members: :undoc-members: :show-inheritance: +diffpy.srfit.pdf.pdfcontribution module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Module contents ---------------- - -.. automodule:: diffpy.srfit.pdf +.. automodule:: diffpy.srfit.pdf.pdfcontribution :members: :undoc-members: :show-inheritance: + diff --git a/doc/source/api/diffpy.srfit.rst b/doc/source/api/diffpy.srfit.rst index 5b2b697b..9eef9e38 100644 --- a/doc/source/api/diffpy.srfit.rst +++ b/doc/source/api/diffpy.srfit.rst @@ -1,9 +1,7 @@ :tocdepth: -1 -|title| -======= - -.. |title| replace:: diffpy.srfit package +diffpy.srfit package +==================== .. automodule:: diffpy.srfit :members: @@ -14,17 +12,24 @@ Subpackages ----------- .. toctree:: - diffpy.srfit.example_package + :titlesonly: + + diffpy.srfit.interface + diffpy.srfit.equation + diffpy.srfit.util + diffpy.srfit.pdf + diffpy.srfit.sas + diffpy.srfit.fitbase + diffpy.srfit.structure Submodules ---------- -|module| --------- +diffpy.srfit.exceptions module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. |module| replace:: diffpy.srfit.example_submodule module - -.. automodule:: diffpy.srfit.example_submodule +.. automodule:: diffpy.srfit.exceptions :members: :undoc-members: :show-inheritance: + diff --git a/doc/source/api/diffpy.srfit.sas.rst b/doc/source/api/diffpy.srfit.sas.rst index 40f24b3d..fbc67925 100644 --- a/doc/source/api/diffpy.srfit.sas.rst +++ b/doc/source/api/diffpy.srfit.sas.rst @@ -1,54 +1,61 @@ +:tocdepth: -1 + diffpy.srfit.sas package ======================== +.. automodule:: diffpy.srfit.sas + :members: + :undoc-members: + :show-inheritance: + Submodules ---------- -diffpy.srfit.sas.prcalculator module ------------------------------------- +diffpy.srfit.sas.sasparser module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.sas.prcalculator +.. automodule:: diffpy.srfit.sas.sasparser :members: :undoc-members: :show-inheritance: -diffpy.srfit.sas.sasgenerator module ------------------------------------- +diffpy.srfit.sas.prcalculator module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.sas.sasgenerator +.. automodule:: diffpy.srfit.sas.prcalculator :members: :undoc-members: :show-inheritance: -diffpy.srfit.sas.sasparameter module ------------------------------------- +diffpy.srfit.sas.sasprofile module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.sas.sasparameter +.. automodule:: diffpy.srfit.sas.sasprofile :members: :undoc-members: :show-inheritance: -diffpy.srfit.sas.sasparser module ---------------------------------- +diffpy.srfit.sas.sasparameter module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.sas.sasparser +.. automodule:: diffpy.srfit.sas.sasparameter :members: :undoc-members: :show-inheritance: -diffpy.srfit.sas.sasprofile module ----------------------------------- +diffpy.srfit.sas.sasimport module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.sas.sasprofile +.. automodule:: diffpy.srfit.sas.sasimport :members: :undoc-members: :show-inheritance: +diffpy.srfit.sas.sasgenerator module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Module contents ---------------- - -.. automodule:: diffpy.srfit.sas +.. automodule:: diffpy.srfit.sas.sasgenerator :members: :undoc-members: :show-inheritance: + diff --git a/doc/source/api/diffpy.srfit.structure.rst b/doc/source/api/diffpy.srfit.structure.rst index 1bb5dd22..1fa5326d 100644 --- a/doc/source/api/diffpy.srfit.structure.rst +++ b/doc/source/api/diffpy.srfit.structure.rst @@ -1,70 +1,69 @@ +:tocdepth: -1 + diffpy.srfit.structure package ============================== +.. automodule:: diffpy.srfit.structure + :members: + :undoc-members: + :show-inheritance: + Submodules ---------- -diffpy.srfit.structure.basestructureparset module -------------------------------------------------- +diffpy.srfit.structure.objcrystparset module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.structure.basestructureparset +.. automodule:: diffpy.srfit.structure.objcrystparset :members: :undoc-members: :show-inheritance: -diffpy.srfit.structure.bvsrestraint module ------------------------------------------- +diffpy.srfit.structure.basestructureparset module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.structure.bvsrestraint +.. automodule:: diffpy.srfit.structure.basestructureparset :members: :undoc-members: :show-inheritance: -diffpy.srfit.structure.cctbxparset module ------------------------------------------ +diffpy.srfit.structure.srrealparset module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.structure.cctbxparset +.. automodule:: diffpy.srfit.structure.srrealparset :members: :undoc-members: :show-inheritance: diffpy.srfit.structure.diffpyparset module ------------------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. automodule:: diffpy.srfit.structure.diffpyparset :members: :undoc-members: :show-inheritance: -diffpy.srfit.structure.objcrystparset module --------------------------------------------- +diffpy.srfit.structure.cctbxparset module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.structure.objcrystparset +.. automodule:: diffpy.srfit.structure.cctbxparset :members: :undoc-members: :show-inheritance: -diffpy.srfit.structure.sgconstraints module -------------------------------------------- +diffpy.srfit.structure.bvsrestraint module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.structure.sgconstraints +.. automodule:: diffpy.srfit.structure.bvsrestraint :members: :undoc-members: :show-inheritance: -diffpy.srfit.structure.srrealparset module ------------------------------------------- +diffpy.srfit.structure.sgconstraints module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.structure.srrealparset +.. automodule:: diffpy.srfit.structure.sgconstraints :members: :undoc-members: :show-inheritance: - -Module contents ---------------- - -.. automodule:: diffpy.srfit.structure - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/source/api/diffpy.srfit.util.rst b/doc/source/api/diffpy.srfit.util.rst index 64541ce6..b96e6945 100644 --- a/doc/source/api/diffpy.srfit.util.rst +++ b/doc/source/api/diffpy.srfit.util.rst @@ -1,46 +1,61 @@ +:tocdepth: -1 + diffpy.srfit.util package ========================= +.. automodule:: diffpy.srfit.util + :members: + :undoc-members: + :show-inheritance: + Submodules ---------- diffpy.srfit.util.inpututils module ------------------------------------ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. automodule:: diffpy.srfit.util.inpututils :members: :undoc-members: :show-inheritance: -diffpy.srfit.util.nameutils module ----------------------------------- +diffpy.srfit.util.observable module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.util.nameutils +.. automodule:: diffpy.srfit.util.observable :members: :undoc-members: :show-inheritance: -diffpy.srfit.util.observable module ------------------------------------ +diffpy.srfit.util.tagmanager module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.util.observable +.. automodule:: diffpy.srfit.util.tagmanager :members: :undoc-members: :show-inheritance: -diffpy.srfit.util.tagmanager module ------------------------------------ +diffpy.srfit.util.argbinders module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.util.tagmanager +.. automodule:: diffpy.srfit.util.argbinders :members: :undoc-members: :show-inheritance: +diffpy.srfit.util.nameutils module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: diffpy.srfit.util.nameutils + :members: + :undoc-members: + :show-inheritance: -Module contents ---------------- +diffpy.srfit.util.weakrefcallable module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.srfit.util +.. automodule:: diffpy.srfit.util.weakrefcallable :members: :undoc-members: :show-inheritance: + From 7dd12c8d779754be44fe46da50358abaddb032c4 Mon Sep 17 00:00:00 2001 From: Tieqiong Zhang Date: Tue, 2 Jul 2024 16:30:55 -0400 Subject: [PATCH 20/21] switch back to unittest run for now --- src/diffpy/srfit/tests/run.py | 40 +++++++++++++++++------------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/diffpy/srfit/tests/run.py b/src/diffpy/srfit/tests/run.py index eeb0a0b0..f1c83fa0 100644 --- a/src/diffpy/srfit/tests/run.py +++ b/src/diffpy/srfit/tests/run.py @@ -1,34 +1,34 @@ #!/usr/bin/env python ############################################################################## # -# (c) 2024 The Trustees of Columbia University in the City of New York. -# All rights reserved. +# diffpy.srfit by DANSE Diffraction group +# Simon J. L. Billinge +# (c) 2010 The Trustees of Columbia University +# in the City of New York. All rights reserved. # -# File coded by: Billinge Group members and community contributors. +# File coded by: Pavol Juhas # -# See GitHub contributions for a more detailed list of contributors. -# https://github.com/diffpy/diffpy.srfit/graphs/contributors -# -# See LICENSE.rst for license information. +# See AUTHORS.txt for a list of people who contributed. +# See LICENSE_DANSE.txt for license information. # ############################################################################## + """Convenience module for executing all unit tests with + python -m diffpy.srfit.tests.run """ -import sys - -import pytest -if __name__ == "__main__": - # show output results from every test function - args = ["-v"] - # show the message output for skipped and expected failure tests - if len(sys.argv) > 1: - args.extend(sys.argv[1:]) - print("pytest arguments: {}".format(args)) - # call pytest and exit with the return code from pytest - exit_res = pytest.main(args) - sys.exit(exit_res) +if __name__ == '__main__': + import sys + # show warnings by default + if not sys.warnoptions: + import os, warnings + warnings.simplefilter("default") + # also affect subprocesses + os.environ["PYTHONWARNINGS"] = "default" + from diffpy.srfit.tests import test + # produce zero exit code for a successful test + sys.exit(not test().wasSuccessful()) # End of file From e19689060d07d44a0ae3e49bc573c746b1e205a7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 2 Jul 2024 20:31:37 +0000 Subject: [PATCH 21/21] [pre-commit.ci] auto fixes from pre-commit hooks --- devutils/makesdist | 38 +-- doc/examples/coreshellnp.py | 57 ++-- doc/examples/crystalpdf.py | 26 +- doc/examples/crystalpdfall.py | 78 +++--- doc/examples/crystalpdfobjcryst.py | 17 +- doc/examples/crystalpdftwodata.py | 36 +-- doc/examples/crystalpdftwophase.py | 43 ++- doc/examples/data/ni.iq | 1 - doc/examples/debyemodel.py | 43 +-- doc/examples/debyemodelII.py | 28 +- doc/examples/ellipsoidsas.py | 20 +- doc/examples/gaussiangenerator.py | 17 +- doc/examples/gaussianrecipe.py | 16 +- doc/examples/interface.py | 9 +- doc/examples/npintensity.py | 56 ++-- doc/examples/npintensityII.py | 84 +++--- doc/examples/nppdfcrystal.py | 29 +- doc/examples/nppdfobjcryst.py | 30 +- doc/examples/nppdfsas.py | 37 +-- doc/examples/simplepdf.py | 17 +- doc/examples/simplepdftwophase.py | 30 +- doc/examples/simplerecipe.py | 3 + doc/examples/threedoublepeaks.py | 57 ++-- .../api/diffpy.srfit.equation.literals.rst | 1 - doc/source/api/diffpy.srfit.equation.rst | 1 - .../api/diffpy.srfit.equation.visitors.rst | 1 - doc/source/api/diffpy.srfit.fitbase.rst | 1 - doc/source/api/diffpy.srfit.interface.rst | 1 - doc/source/api/diffpy.srfit.pdf.rst | 1 - doc/source/api/diffpy.srfit.rst | 1 - doc/source/api/diffpy.srfit.sas.rst | 1 - doc/source/api/diffpy.srfit.structure.rst | 1 - doc/source/api/diffpy.srfit.util.rst | 1 - src/diffpy/__init__.py | 1 - src/diffpy/srfit/equation/__init__.py | 1 - src/diffpy/srfit/equation/builder.py | 111 +++++--- src/diffpy/srfit/equation/equationmod.py | 26 +- .../srfit/equation/literals/__init__.py | 59 ++-- src/diffpy/srfit/equation/literals/abcs.py | 15 +- .../srfit/equation/literals/argument.py | 10 +- src/diffpy/srfit/equation/literals/literal.py | 6 +- .../srfit/equation/literals/operators.py | 32 ++- .../srfit/equation/visitors/__init__.py | 6 +- .../srfit/equation/visitors/argfinder.py | 3 +- src/diffpy/srfit/equation/visitors/printer.py | 16 +- src/diffpy/srfit/equation/visitors/swapper.py | 3 +- .../srfit/equation/visitors/validator.py | 15 +- src/diffpy/srfit/equation/visitors/visitor.py | 4 +- src/diffpy/srfit/exceptions.py | 2 + src/diffpy/srfit/fitbase/__init__.py | 17 +- src/diffpy/srfit/fitbase/calculator.py | 8 +- src/diffpy/srfit/fitbase/configurable.py | 1 + src/diffpy/srfit/fitbase/constraint.py | 8 +- src/diffpy/srfit/fitbase/fitcontribution.py | 44 ++- src/diffpy/srfit/fitbase/fithook.py | 16 +- src/diffpy/srfit/fitbase/fitrecipe.py | 115 ++++---- src/diffpy/srfit/fitbase/fitresults.py | 109 ++++---- src/diffpy/srfit/fitbase/parameter.py | 35 +-- src/diffpy/srfit/fitbase/parameterset.py | 3 +- src/diffpy/srfit/fitbase/profile.py | 59 ++-- src/diffpy/srfit/fitbase/profilegenerator.py | 7 +- src/diffpy/srfit/fitbase/profileparser.py | 5 +- src/diffpy/srfit/fitbase/recipeorganizer.py | 137 +++++----- src/diffpy/srfit/fitbase/restraint.py | 10 +- src/diffpy/srfit/fitbase/simplerecipe.py | 25 +- src/diffpy/srfit/fitbase/validatable.py | 4 +- src/diffpy/srfit/interface/__init__.py | 3 + src/diffpy/srfit/interface/interface.py | 19 +- src/diffpy/srfit/pdf/__init__.py | 2 +- src/diffpy/srfit/pdf/basepdfgenerator.py | 31 +-- .../srfit/pdf/characteristicfunctions.py | 157 +++++++---- src/diffpy/srfit/pdf/debyepdfgenerator.py | 13 +- src/diffpy/srfit/pdf/pdfcontribution.py | 25 +- src/diffpy/srfit/pdf/pdfgenerator.py | 7 +- src/diffpy/srfit/pdf/pdfparser.py | 39 +-- src/diffpy/srfit/sas/__init__.py | 5 +- src/diffpy/srfit/sas/prcalculator.py | 6 +- src/diffpy/srfit/sas/sasgenerator.py | 1 + src/diffpy/srfit/sas/sasimport.py | 24 +- src/diffpy/srfit/sas/sasparameter.py | 5 +- src/diffpy/srfit/sas/sasparser.py | 6 +- src/diffpy/srfit/sas/sasprofile.py | 2 +- src/diffpy/srfit/structure/__init__.py | 4 + src/diffpy/srfit/structure/bvsrestraint.py | 18 +- src/diffpy/srfit/structure/cctbxparset.py | 56 ++-- src/diffpy/srfit/structure/diffpyparset.py | 74 +++-- src/diffpy/srfit/structure/objcrystparset.py | 257 +++++++++--------- src/diffpy/srfit/structure/sgconstraints.py | 161 ++++++----- src/diffpy/srfit/structure/srrealparset.py | 5 +- src/diffpy/srfit/tests/__init__.py | 26 +- src/diffpy/srfit/tests/run.py | 8 +- src/diffpy/srfit/tests/speedtest.py | 120 ++++---- src/diffpy/srfit/tests/testbuilder.py | 71 +++-- .../tests/testcharacteristicfunctions.py | 45 ++- src/diffpy/srfit/tests/testconstraint.py | 4 +- src/diffpy/srfit/tests/testcontribution.py | 76 +++--- src/diffpy/srfit/tests/testdiffpyparset.py | 37 ++- src/diffpy/srfit/tests/testequation.py | 35 ++- src/diffpy/srfit/tests/testfitrecipe.py | 62 ++--- src/diffpy/srfit/tests/testfitresults.py | 8 +- src/diffpy/srfit/tests/testliterals.py | 56 ++-- src/diffpy/srfit/tests/testobjcrystparset.py | 154 +++++------ src/diffpy/srfit/tests/testparameter.py | 19 +- src/diffpy/srfit/tests/testpdf.py | 142 ++++++---- src/diffpy/srfit/tests/testprofile.py | 66 +++-- .../srfit/tests/testprofilegenerator.py | 11 +- src/diffpy/srfit/tests/testrecipeorganizer.py | 127 ++++----- src/diffpy/srfit/tests/testrestraint.py | 7 +- src/diffpy/srfit/tests/testsas.py | 35 +-- src/diffpy/srfit/tests/testsgconstraints.py | 64 +++-- src/diffpy/srfit/tests/testtagmanager.py | 24 +- src/diffpy/srfit/tests/testvisitors.py | 6 +- src/diffpy/srfit/tests/testweakrefcallable.py | 54 ++-- src/diffpy/srfit/tests/utils.py | 37 ++- src/diffpy/srfit/util/__init__.py | 9 +- src/diffpy/srfit/util/argbinders.py | 9 +- src/diffpy/srfit/util/inpututils.py | 3 +- src/diffpy/srfit/util/nameutils.py | 8 +- src/diffpy/srfit/util/observable.py | 8 +- src/diffpy/srfit/util/tagmanager.py | 9 - src/diffpy/srfit/util/weakrefcallable.py | 24 +- 121 files changed, 2066 insertions(+), 1913 deletions(-) diff --git a/devutils/makesdist b/devutils/makesdist index 6aaae616..e77257ea 100755 --- a/devutils/makesdist +++ b/devutils/makesdist @@ -1,51 +1,57 @@ #!/usr/bin/env python -'''Create source distribution tar.gz archive, where each file belongs +"""Create source distribution tar.gz archive, where each file belongs to a root user and modification time is set to the git commit time. -''' +""" -import sys +import glob +import gzip import os import subprocess -import glob +import sys import tarfile -import gzip BASEDIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) sys.path.insert(0, BASEDIR) -from setup import versiondata, FALLBACK_VERSION -timestamp = versiondata.getint('DEFAULT', 'timestamp') +from setup import FALLBACK_VERSION, versiondata -vfb = versiondata.get('DEFAULT', 'version').split('.post')[0] + '.post0' +timestamp = versiondata.getint("DEFAULT", "timestamp") + +vfb = versiondata.get("DEFAULT", "version").split(".post")[0] + ".post0" emsg = "Invalid FALLBACK_VERSION. Expected %r got %r." assert vfb == FALLBACK_VERSION, emsg % (vfb, FALLBACK_VERSION) + def inform(s): sys.stdout.write(s) sys.stdout.flush() return + inform('Run "setup.py sdist --formats=tar" ') -cmd_sdist = [sys.executable] + 'setup.py sdist --formats=tar'.split() -ec = subprocess.call(cmd_sdist, cwd=BASEDIR, stdout=open(os.devnull, 'w')) -if ec: sys.exit(ec) +cmd_sdist = [sys.executable] + "setup.py sdist --formats=tar".split() +ec = subprocess.call(cmd_sdist, cwd=BASEDIR, stdout=open(os.devnull, "w")) +if ec: + sys.exit(ec) inform("[done]\n") -tarname = max(glob.glob(BASEDIR + '/dist/*.tar'), key=os.path.getmtime) +tarname = max(glob.glob(BASEDIR + "/dist/*.tar"), key=os.path.getmtime) tfin = tarfile.open(tarname) -fpout = gzip.GzipFile(tarname + '.gz', 'w', mtime=0) -tfout = tarfile.open(fileobj=fpout, mode='w') +fpout = gzip.GzipFile(tarname + ".gz", "w", mtime=0) +tfout = tarfile.open(fileobj=fpout, mode="w") + def fixtarinfo(tinfo): tinfo.uid = tinfo.gid = 0 - tinfo.uname = tinfo.gname = 'root' + tinfo.uname = tinfo.gname = "root" tinfo.mtime = timestamp tinfo.mode &= ~0o022 return tinfo -inform('Filter %s --> %s.gz ' % (2 * (os.path.basename(tarname),))) + +inform("Filter %s --> %s.gz " % (2 * (os.path.basename(tarname),))) for ti in tfin: tfout.addfile(fixtarinfo(ti), tfin.extractfile(ti)) diff --git a/doc/examples/coreshellnp.py b/doc/examples/coreshellnp.py index 9c806647..7e464c74 100644 --- a/doc/examples/coreshellnp.py +++ b/doc/examples/coreshellnp.py @@ -22,17 +22,15 @@ """ import numpy -from scipy.optimize import leastsq - from pyobjcryst import loadCrystal +from scipy.optimize import leastsq +from diffpy.srfit.fitbase import FitContribution, FitRecipe, FitResults, Profile from diffpy.srfit.pdf import PDFGenerator, PDFParser -from diffpy.srfit.fitbase import Profile -from diffpy.srfit.fitbase import FitContribution, FitRecipe -from diffpy.srfit.fitbase import FitResults ####### Example Code + def makeRecipe(stru1, stru2, datname): """Create a fitting recipe for crystalline PDF data.""" @@ -43,7 +41,7 @@ def makeRecipe(stru1, stru2, datname): parser = PDFParser() parser.parseFile(datname) profile.loadParsedData(parser) - profile.setCalculationRange(xmin=1.5, xmax = 45, dx = 0.1) + profile.setCalculationRange(xmin=1.5, xmax=45, dx=0.1) ## The ProfileGenerator # In order to fit the core and shell phases simultaneously, we must use two @@ -66,15 +64,16 @@ def makeRecipe(stru1, stru2, datname): contribution = FitContribution("cdszns") contribution.addProfileGenerator(generator_cds) contribution.addProfileGenerator(generator_zns) - contribution.setProfile(profile, xname = "r") + contribution.setProfile(profile, xname="r") # Set up the characteristic functions. We use a spherical CF for the core # and a spherical shell CF for the shell. Since this is set up as two # phases, we implicitly assume that the core-shell correlations contribute # very little to the PDF. - from diffpy.srfit.pdf.characteristicfunctions import sphericalCF, shellCF - contribution.registerFunction(sphericalCF, name = "f_CdS") - contribution.registerFunction(shellCF, name = "f_ZnS") + from diffpy.srfit.pdf.characteristicfunctions import shellCF, sphericalCF + + contribution.registerFunction(sphericalCF, name="f_CdS") + contribution.registerFunction(shellCF, name="f_ZnS") # Write the fitting equation. We want to sum the PDFs from each phase and # multiply it by a scaling factor. @@ -106,27 +105,28 @@ def makeRecipe(stru1, stru2, datname): # subsequent refinement. phase_cds = generator_cds.phase for par in phase_cds.sgpars.latpars: - recipe.addVar(par, name = par.name + "_cds", tag = "lat") + recipe.addVar(par, name=par.name + "_cds", tag="lat") for par in phase_cds.sgpars.adppars: - recipe.addVar(par, 1, name = par.name + "_cds", tag = "adp") - recipe.addVar(phase_cds.sgpars.xyzpars.z_1, name = "z_1_cds", tag = "xyz") + recipe.addVar(par, 1, name=par.name + "_cds", tag="adp") + recipe.addVar(phase_cds.sgpars.xyzpars.z_1, name="z_1_cds", tag="xyz") # Since we know these have stacking disorder, constrain the B33 adps for # each atom type. recipe.constrain("B33_1_cds", "B33_0_cds") - recipe.addVar(generator_cds.delta2, name = "delta2_cds", value = 5) + recipe.addVar(generator_cds.delta2, name="delta2_cds", value=5) phase_zns = generator_zns.phase for par in phase_zns.sgpars.latpars: - recipe.addVar(par, name = par.name + "_zns", tag = "lat") + recipe.addVar(par, name=par.name + "_zns", tag="lat") for par in phase_zns.sgpars.adppars: - recipe.addVar(par, 1, name = par.name + "_zns", tag = "adp") - recipe.addVar(phase_zns.sgpars.xyzpars.z_1, name = "z_1_zns", tag = "xyz") + recipe.addVar(par, 1, name=par.name + "_zns", tag="adp") + recipe.addVar(phase_zns.sgpars.xyzpars.z_1, name="z_1_zns", tag="xyz") recipe.constrain("B33_1_zns", "B33_0_zns") - recipe.addVar(generator_zns.delta2, name = "delta2_zns", value = 2.5) + recipe.addVar(generator_zns.delta2, name="delta2_zns", value=2.5) # Give the recipe away so it can be used! return recipe + def plotResults(recipe): """Plot the results contained within a refined FitRecipe.""" @@ -138,10 +138,11 @@ def plotResults(recipe): diff = g - gcalc + diffzero import pylab - pylab.plot(r,g,'bo',label="G(r) Data") - pylab.plot(r, gcalc,'r-',label="G(r) Fit") - pylab.plot(r,diff,'g-',label="G(r) diff") - pylab.plot(r,diffzero,'k-') + + pylab.plot(r, g, "bo", label="G(r) Data") + pylab.plot(r, gcalc, "r-", label="G(r) Fit") + pylab.plot(r, diff, "g-", label="G(r) diff") + pylab.plot(r, diffzero, "k-") pylab.xlabel(r"$r (\AA)$") pylab.ylabel(r"$G (\AA^{-2})$") pylab.legend(loc=1) @@ -163,6 +164,7 @@ def main(): stru2 = loadCrystal(znsciffile) recipe = makeRecipe(stru1, stru2, data) from diffpy.srfit.fitbase.fithook import PlotFitHook + recipe.pushFitHook(PlotFitHook()) recipe.fithooks[0].verbose = 3 @@ -172,23 +174,23 @@ def main(): # Start with the lattice parameters. In makeRecipe, these were tagged with # "lat". Here is how we use that. recipe.free("lat") - leastsq(recipe.residual, recipe.values, maxfev = 50) + leastsq(recipe.residual, recipe.values, maxfev=50) # Now the scale and phase fraction. recipe.free("scale", "scale_CdS") - leastsq(recipe.residual, recipe.values, maxfev = 50) + leastsq(recipe.residual, recipe.values, maxfev=50) # The ADPs. recipe.free("adp") - leastsq(recipe.residual, recipe.values, maxfev = 100) + leastsq(recipe.residual, recipe.values, maxfev=100) # The delta2 parameters. recipe.free("delta2_cds", "delta2_zns") - leastsq(recipe.residual, recipe.values, maxfev = 50) + leastsq(recipe.residual, recipe.values, maxfev=50) # The shape parameters. recipe.free("radius", "thickness") - leastsq(recipe.residual, recipe.values, maxfev = 50) + leastsq(recipe.residual, recipe.values, maxfev=50) # The positional parameters. recipe.free("xyz") @@ -202,6 +204,7 @@ def main(): plotResults(recipe) return + if __name__ == "__main__": main() diff --git a/doc/examples/crystalpdf.py b/doc/examples/crystalpdf.py index ced49e9a..f410f3c9 100644 --- a/doc/examples/crystalpdf.py +++ b/doc/examples/crystalpdf.py @@ -26,17 +26,15 @@ """ import numpy +from gaussianrecipe import scipyOptimize -from diffpy.structure import Structure +from diffpy.srfit.fitbase import FitContribution, FitRecipe, FitResults, Profile from diffpy.srfit.pdf import PDFGenerator, PDFParser -from diffpy.srfit.fitbase import Profile -from diffpy.srfit.fitbase import FitContribution, FitRecipe -from diffpy.srfit.fitbase import FitResults - -from gaussianrecipe import scipyOptimize +from diffpy.structure import Structure ####### Example Code + def makeRecipe(ciffile, datname): """Create a fitting recipe for crystalline PDF data.""" @@ -53,7 +51,7 @@ def makeRecipe(ciffile, datname): parser = PDFParser() parser.parseFile(datname) profile.loadParsedData(parser) - profile.setCalculationRange(xmax = 20) + profile.setCalculationRange(xmax=20) ## The ProfileGenerator # The PDFGenerator is for configuring and calculating a PDF profile. Here, @@ -72,7 +70,7 @@ def makeRecipe(ciffile, datname): # before. contribution = FitContribution("nickel") contribution.addProfileGenerator(generator) - contribution.setProfile(profile, xname = "r") + contribution.setProfile(profile, xname="r") ## Make the FitRecipe and add the FitContribution. recipe = FitRecipe() @@ -95,6 +93,7 @@ def makeRecipe(ciffile, datname): # documentation for more details. The 'constrainAsSpaceGroup' method may # create new Parameters, which it returns in a SpaceGroupParameters object. from diffpy.srfit.structure import constrainAsSpaceGroup + sgpars = constrainAsSpaceGroup(phase, "Fm-3m") # The SpaceGroupParameters object returned by 'constrainAsSpaceGroup' holds @@ -124,6 +123,7 @@ def makeRecipe(ciffile, datname): # Give the recipe away so it can be used! return recipe + def plotResults(recipe): """Plot the results contained within a refined FitRecipe.""" @@ -135,10 +135,11 @@ def plotResults(recipe): diff = g - gcalc + diffzero import pylab - pylab.plot(r,g,'bo',label="G(r) Data") - pylab.plot(r, gcalc,'r-',label="G(r) Fit") - pylab.plot(r,diff,'g-',label="G(r) diff") - pylab.plot(r,diffzero,'k-') + + pylab.plot(r, g, "bo", label="G(r) Data") + pylab.plot(r, gcalc, "r-", label="G(r) Fit") + pylab.plot(r, diff, "g-", label="G(r) diff") + pylab.plot(r, diffzero, "k-") pylab.xlabel(r"$r (\AA)$") pylab.ylabel(r"$G (\AA^{-2})$") pylab.legend(loc=1) @@ -146,6 +147,7 @@ def plotResults(recipe): pylab.show() return + if __name__ == "__main__": # Make the data and the recipe diff --git a/doc/examples/crystalpdfall.py b/doc/examples/crystalpdfall.py index c79cf6c5..4cd860c1 100644 --- a/doc/examples/crystalpdfall.py +++ b/doc/examples/crystalpdfall.py @@ -20,36 +20,34 @@ """ import numpy - +from gaussianrecipe import scipyOptimize from pyobjcryst import loadCrystal +from diffpy.srfit.fitbase import FitContribution, FitRecipe, FitResults, Profile from diffpy.srfit.pdf import PDFGenerator, PDFParser -from diffpy.srfit.fitbase import Profile -from diffpy.srfit.fitbase import FitContribution, FitRecipe -from diffpy.srfit.fitbase import FitResults - -from gaussianrecipe import scipyOptimize ####### Example Code + def makeProfile(datafile): """Make an place data within a Profile.""" profile = Profile() parser = PDFParser() parser.parseFile(datafile) profile.loadParsedData(parser) - profile.setCalculationRange(xmax = 20) + profile.setCalculationRange(xmax=20) return profile + def makeContribution(name, generator, profile): """Make a FitContribution and add a generator and profile.""" contribution = FitContribution(name) contribution.addProfileGenerator(generator) - contribution.setProfile(profile, xname = "r") + contribution.setProfile(profile, xname="r") return contribution -def makeRecipe(ciffile_ni, ciffile_si, xdata_ni, ndata_ni, xdata_si, - xdata_sini): + +def makeRecipe(ciffile_ni, ciffile_si, xdata_ni, ndata_ni, xdata_si, xdata_sini): """Create a fitting recipe for crystalline PDF data.""" ## The Profiles @@ -85,8 +83,7 @@ def makeRecipe(ciffile_ni, ciffile_si, xdata_ni, ndata_ni, xdata_si, xcontribution_ni = makeContribution("xnickel", xgenerator_ni, xprofile_ni) xcontribution_si = makeContribution("xsilicon", xgenerator_si, xprofile_si) ncontribution_ni = makeContribution("nnickel", ngenerator_ni, nprofile_ni) - xcontribution_sini = makeContribution("xsini", xgenerator_sini_ni, - xprofile_sini) + xcontribution_sini = makeContribution("xsini", xgenerator_sini_ni, xprofile_sini) xcontribution_sini.addProfileGenerator(xgenerator_sini_si) xcontribution_sini.setEquation("scale * (xG_sini_ni + xG_sini_si)") @@ -105,22 +102,22 @@ def makeRecipe(ciffile_ni, ciffile_si, xdata_ni, ndata_ni, xdata_si, # Now we vary and constrain Parameters as before. for par in phase_ni.sgpars: - recipe.addVar(par, name = par.name + "_ni") + recipe.addVar(par, name=par.name + "_ni") delta2_ni = recipe.newVar("delta2_ni", 2.5) recipe.constrain(xgenerator_ni.delta2, delta2_ni) recipe.constrain(ngenerator_ni.delta2, delta2_ni) recipe.constrain(xgenerator_sini_ni.delta2, delta2_ni) for par in phase_si.sgpars: - recipe.addVar(par, name = par.name + "_si") + recipe.addVar(par, name=par.name + "_si") delta2_si = recipe.newVar("delta2_si", 2.5) recipe.constrain(xgenerator_si.delta2, delta2_si) recipe.constrain(xgenerator_sini_si.delta2, delta2_si) # Now the experimental parameters - recipe.addVar(xgenerator_ni.scale, name = "xscale_ni") - recipe.addVar(xgenerator_si.scale, name = "xscale_si") - recipe.addVar(ngenerator_ni.scale, name = "nscale_ni") + recipe.addVar(xgenerator_ni.scale, name="xscale_ni") + recipe.addVar(xgenerator_si.scale, name="xscale_si") + recipe.addVar(ngenerator_ni.scale, name="nscale_ni") recipe.addVar(xcontribution_sini.scale, 1.0, "xscale_sini") recipe.newVar("pscale_sini_ni", 0.8) recipe.constrain(xgenerator_sini_ni.scale, "pscale_sini_ni") @@ -137,6 +134,7 @@ def makeRecipe(ciffile_ni, ciffile_si, xdata_ni, ndata_ni, xdata_si, # Give the recipe away so it can be used! return recipe + def plotResults(recipe): """Plot the results contained within a refined FitRecipe.""" @@ -145,65 +143,66 @@ def plotResults(recipe): xr_ni = xnickel.profile.x xg_ni = xnickel.profile.y xgcalc_ni = xnickel.profile.ycalc - xdiffzero_ni = -0.8 * max(xg_ni) * numpy.ones_like(xg_ni) + xdiffzero_ni = -0.8 * max(xg_ni) * numpy.ones_like(xg_ni) xdiff_ni = xg_ni - xgcalc_ni + xdiffzero_ni xsilicon = recipe.xsilicon xr_si = xsilicon.profile.x xg_si = xsilicon.profile.y xgcalc_si = xsilicon.profile.ycalc - xdiffzero_si = -0.8 * max(xg_si) * numpy.ones_like(xg_si) + xdiffzero_si = -0.8 * max(xg_si) * numpy.ones_like(xg_si) xdiff_si = xg_si - xgcalc_si + xdiffzero_si nnickel = recipe.nnickel nr_ni = nnickel.profile.x ng_ni = nnickel.profile.y ngcalc_ni = nnickel.profile.ycalc - ndiffzero_ni = -0.8 * max(ng_ni) * numpy.ones_like(ng_ni) + ndiffzero_ni = -0.8 * max(ng_ni) * numpy.ones_like(ng_ni) ndiff_ni = ng_ni - ngcalc_ni + ndiffzero_ni xsini = recipe.xsini xr_sini = xsini.profile.x xg_sini = xsini.profile.y xgcalc_sini = xsini.profile.ycalc - xdiffzero_sini = -0.8 * max(xg_sini) * numpy.ones_like(xg_sini) + xdiffzero_sini = -0.8 * max(xg_sini) * numpy.ones_like(xg_sini) xdiff_sini = xg_sini - xgcalc_sini + xdiffzero_sini - import pylab + pylab.subplot(2, 2, 1) - pylab.plot(xr_ni,xg_ni,'bo',label="G(r) x-ray nickel Data") - pylab.plot(xr_ni,xgcalc_ni,'r-',label="G(r) x-ray nickel Fit") - pylab.plot(xr_ni,xdiff_ni,'g-',label="G(r) x-ray nickel diff") - pylab.plot(xr_ni,xdiffzero_ni,'k-') + pylab.plot(xr_ni, xg_ni, "bo", label="G(r) x-ray nickel Data") + pylab.plot(xr_ni, xgcalc_ni, "r-", label="G(r) x-ray nickel Fit") + pylab.plot(xr_ni, xdiff_ni, "g-", label="G(r) x-ray nickel diff") + pylab.plot(xr_ni, xdiffzero_ni, "k-") pylab.xlabel(r"$r (\AA)$") pylab.ylabel(r"$G (\AA^{-2})$") pylab.legend(loc=1) pylab.subplot(2, 2, 2) - pylab.plot(xr_si,xg_si,'bo',label="G(r) x-ray silicon Data") - pylab.plot(xr_si,xgcalc_si,'r-',label="G(r) x-ray silicon Fit") - pylab.plot(xr_si,xdiff_si,'g-',label="G(r) x-ray silicon diff") - pylab.plot(xr_si,xdiffzero_si,'k-') + pylab.plot(xr_si, xg_si, "bo", label="G(r) x-ray silicon Data") + pylab.plot(xr_si, xgcalc_si, "r-", label="G(r) x-ray silicon Fit") + pylab.plot(xr_si, xdiff_si, "g-", label="G(r) x-ray silicon diff") + pylab.plot(xr_si, xdiffzero_si, "k-") pylab.legend(loc=1) pylab.subplot(2, 2, 3) - pylab.plot(nr_ni,ng_ni,'bo',label="G(r) neutron nickel Data") - pylab.plot(nr_ni,ngcalc_ni,'r-',label="G(r) neutron nickel Fit") - pylab.plot(nr_ni,ndiff_ni,'g-',label="G(r) neutron nickel diff") - pylab.plot(nr_ni,ndiffzero_ni,'k-') + pylab.plot(nr_ni, ng_ni, "bo", label="G(r) neutron nickel Data") + pylab.plot(nr_ni, ngcalc_ni, "r-", label="G(r) neutron nickel Fit") + pylab.plot(nr_ni, ndiff_ni, "g-", label="G(r) neutron nickel diff") + pylab.plot(nr_ni, ndiffzero_ni, "k-") pylab.legend(loc=1) pylab.subplot(2, 2, 4) - pylab.plot(xr_sini,xg_sini,'bo',label="G(r) x-ray sini Data") - pylab.plot(xr_sini,xgcalc_sini,'r-',label="G(r) x-ray sini Fit") - pylab.plot(xr_sini,xdiff_sini,'g-',label="G(r) x-ray sini diff") - pylab.plot(xr_sini,xdiffzero_sini,'k-') + pylab.plot(xr_sini, xg_sini, "bo", label="G(r) x-ray sini Data") + pylab.plot(xr_sini, xgcalc_sini, "r-", label="G(r) x-ray sini Fit") + pylab.plot(xr_sini, xdiff_sini, "g-", label="G(r) x-ray sini diff") + pylab.plot(xr_sini, xdiffzero_sini, "k-") pylab.legend(loc=1) pylab.show() return + if __name__ == "__main__": # Make the data and the recipe @@ -215,8 +214,7 @@ def plotResults(recipe): xdata_sini = "data/si90ni10-q27r60-xray.gr" # Make the recipe - recipe = makeRecipe(ciffile_ni, ciffile_si, xdata_ni, ndata_ni, xdata_si, - xdata_sini) + recipe = makeRecipe(ciffile_ni, ciffile_si, xdata_ni, ndata_ni, xdata_si, xdata_sini) # Optimize scipyOptimize(recipe) diff --git a/doc/examples/crystalpdfobjcryst.py b/doc/examples/crystalpdfobjcryst.py index c7201493..103762bf 100644 --- a/doc/examples/crystalpdfobjcryst.py +++ b/doc/examples/crystalpdfobjcryst.py @@ -20,18 +20,16 @@ by the ObjCrystCrystalParSet structure adapter. """ +from crystalpdf import plotResults +from gaussianrecipe import scipyOptimize from pyobjcryst import loadCrystal +from diffpy.srfit.fitbase import FitContribution, FitRecipe, FitResults, Profile from diffpy.srfit.pdf import PDFGenerator, PDFParser -from diffpy.srfit.fitbase import Profile -from diffpy.srfit.fitbase import FitContribution, FitRecipe -from diffpy.srfit.fitbase import FitResults - -from gaussianrecipe import scipyOptimize -from crystalpdf import plotResults ####### Example Code + def makeRecipe(ciffile, datname): """Create a fitting recipe for crystalline PDF data.""" @@ -46,7 +44,7 @@ def makeRecipe(ciffile, datname): parser = PDFParser() parser.parseFile(datname) profile.loadParsedData(parser) - profile.setCalculationRange(xmax = 20) + profile.setCalculationRange(xmax=20) ## The ProfileGenerator # This time we use the CreateCrystalFromCIF method of pyobjcryst.crystal to @@ -60,7 +58,7 @@ def makeRecipe(ciffile, datname): ## The FitContribution contribution = FitContribution("nickel") contribution.addProfileGenerator(generator) - contribution.setProfile(profile, xname = "r") + contribution.setProfile(profile, xname="r") # Make the FitRecipe and add the FitContribution. recipe = FitRecipe() @@ -89,7 +87,7 @@ def makeRecipe(ciffile, datname): for par in phase.sgpars: recipe.addVar(par) # set the initial thermal factor to a non-zero value - assert hasattr(recipe, 'B11_0') + assert hasattr(recipe, "B11_0") recipe.B11_0 = 0.1 # We now select non-structural parameters to refine. @@ -103,6 +101,7 @@ def makeRecipe(ciffile, datname): # Give the recipe away so it can be used! return recipe + if __name__ == "__main__": # Make the data and the recipe diff --git a/doc/examples/crystalpdftwodata.py b/doc/examples/crystalpdftwodata.py index a43da784..f8b21362 100644 --- a/doc/examples/crystalpdftwodata.py +++ b/doc/examples/crystalpdftwodata.py @@ -22,18 +22,15 @@ """ import numpy - +from gaussianrecipe import scipyOptimize from pyobjcryst import loadCrystal +from diffpy.srfit.fitbase import FitContribution, FitRecipe, FitResults, Profile from diffpy.srfit.pdf import PDFGenerator, PDFParser -from diffpy.srfit.fitbase import Profile -from diffpy.srfit.fitbase import FitContribution, FitRecipe -from diffpy.srfit.fitbase import FitResults - -from gaussianrecipe import scipyOptimize ####### Example Code + def makeRecipe(ciffile, xdatname, ndatname): """Create a fitting recipe for crystalline PDF data.""" @@ -47,12 +44,12 @@ def makeRecipe(ciffile, xdatname, ndatname): parser = PDFParser() parser.parseFile(xdatname) xprofile.loadParsedData(parser) - xprofile.setCalculationRange(xmax = 20) + xprofile.setCalculationRange(xmax=20) parser = PDFParser() parser.parseFile(ndatname) nprofile.loadParsedData(parser) - nprofile.setCalculationRange(xmax = 20) + nprofile.setCalculationRange(xmax=20) ## The ProfileGenerators # We need one of these for the x-ray data. @@ -83,11 +80,11 @@ def makeRecipe(ciffile, xdatname, ndatname): # We associate the x-ray PDFGenerator and Profile in one FitContribution... xcontribution = FitContribution("xnickel") xcontribution.addProfileGenerator(xgenerator) - xcontribution.setProfile(xprofile, xname = "r") + xcontribution.setProfile(xprofile, xname="r") # and the neutron objects in another. ncontribution = FitContribution("nnickel") ncontribution.addProfileGenerator(ngenerator) - ncontribution.setProfile(nprofile, xname = "r") + ncontribution.setProfile(nprofile, xname="r") # This example is different than the previous ones in that we are composing # a residual function from other residuals (one for the x-ray contribution @@ -132,6 +129,7 @@ def makeRecipe(ciffile, xdatname, ndatname): # Give the recipe away so it can be used! return recipe + def plotResults(recipe): """Plot the results contained within a refined FitRecipe.""" @@ -149,18 +147,19 @@ def plotResults(recipe): ndiff = ng - ngcalc + ndiffzero import pylab + pylab.subplot(2, 1, 1) - pylab.plot(xr,xg,'bo',label="G(r) x-ray Data") - pylab.plot(xr,xgcalc,'r-',label="G(r) x-ray Fit") - pylab.plot(xr,xdiff,'g-',label="G(r) x-ray diff") - pylab.plot(xr,xdiffzero,'k-') + pylab.plot(xr, xg, "bo", label="G(r) x-ray Data") + pylab.plot(xr, xgcalc, "r-", label="G(r) x-ray Fit") + pylab.plot(xr, xdiff, "g-", label="G(r) x-ray diff") + pylab.plot(xr, xdiffzero, "k-") pylab.legend(loc=1) pylab.subplot(2, 1, 2) - pylab.plot(nr,ng,'bo',label="G(r) neutron Data") - pylab.plot(nr,ngcalc,'r-',label="G(r) neutron Fit") - pylab.plot(nr,ndiff,'g-',label="G(r) neutron diff") - pylab.plot(nr,ndiffzero,'k-') + pylab.plot(nr, ng, "bo", label="G(r) neutron Data") + pylab.plot(nr, ngcalc, "r-", label="G(r) neutron Fit") + pylab.plot(nr, ndiff, "g-", label="G(r) neutron diff") + pylab.plot(nr, ndiffzero, "k-") pylab.xlabel(r"$r (\AA)$") pylab.ylabel(r"$G (\AA^{-2})$") pylab.legend(loc=1) @@ -168,6 +167,7 @@ def plotResults(recipe): pylab.show() return + if __name__ == "__main__": # Make the data and the recipe diff --git a/doc/examples/crystalpdftwophase.py b/doc/examples/crystalpdftwophase.py index df7cce77..57f83e53 100644 --- a/doc/examples/crystalpdftwophase.py +++ b/doc/examples/crystalpdftwophase.py @@ -22,18 +22,15 @@ """ import numpy - +from gaussianrecipe import scipyOptimize from pyobjcryst import loadCrystal +from diffpy.srfit.fitbase import FitContribution, FitRecipe, FitResults, Profile from diffpy.srfit.pdf import PDFGenerator, PDFParser -from diffpy.srfit.fitbase import Profile -from diffpy.srfit.fitbase import FitContribution, FitRecipe -from diffpy.srfit.fitbase import FitResults - -from gaussianrecipe import scipyOptimize ####### Example Code + def makeRecipe(niciffile, siciffile, datname): """Create a fitting recipe for crystalline PDF data.""" @@ -44,7 +41,7 @@ def makeRecipe(niciffile, siciffile, datname): parser = PDFParser() parser.parseFile(datname) profile.loadParsedData(parser) - profile.setCalculationRange(xmax = 20) + profile.setCalculationRange(xmax=20) ## The ProfileGenerator # In order to fit two phases simultaneously, we must use two PDFGenerators. @@ -72,7 +69,7 @@ def makeRecipe(niciffile, siciffile, datname): contribution = FitContribution("nisi") contribution.addProfileGenerator(generator_ni) contribution.addProfileGenerator(generator_si) - contribution.setProfile(profile, xname = "r") + contribution.setProfile(profile, xname="r") # Write the fitting equation. We want to sum the PDFs from each phase and # multiply it by a scaling factor. We also want a certain phase scaling @@ -105,13 +102,13 @@ def makeRecipe(niciffile, siciffile, datname): # First the nickel parameters phase_ni = generator_ni.phase for par in phase_ni.sgpars: - recipe.addVar(par, name = par.name + "_ni") - recipe.addVar(generator_ni.delta2, name = "delta2_ni") + recipe.addVar(par, name=par.name + "_ni") + recipe.addVar(generator_ni.delta2, name="delta2_ni") # Next the silicon parameters phase_si = generator_si.phase for par in phase_si.sgpars: - recipe.addVar(par, name = par.name + "_si") - recipe.addVar(generator_si.delta2, name = "delta2_si") + recipe.addVar(par, name=par.name + "_si") + recipe.addVar(generator_si.delta2, name="delta2_si") # We have prior information from the earlier examples so we'll use it here # in the form of restraints. @@ -121,22 +118,23 @@ def makeRecipe(niciffile, siciffile, datname): # derived has no uncertainty. Thus, we will tell the recipe to scale the # residual, which means that it will be weighted as much as the average # data point during the fit. - recipe.restrain("a_ni", lb = 3.527, ub = 3.527, scaled = True) + recipe.restrain("a_ni", lb=3.527, ub=3.527, scaled=True) # Now we do the same with the delta2 and Biso parameters (remember that # Biso = 8*pi**2*Uiso) - recipe.restrain("delta2_ni", lb = 2.22, ub = 2.22, scaled = True) - recipe.restrain("Biso_0_ni", lb = 0.454, ub = 0.454, scaled = True) + recipe.restrain("delta2_ni", lb=2.22, ub=2.22, scaled=True) + recipe.restrain("Biso_0_ni", lb=0.454, ub=0.454, scaled=True) # # We can do the same with the silicon values. We haven't done a thorough # job of measuring the uncertainties in the results, so we'll scale these # as well. - recipe.restrain("a_si", lb = 5.430, ub = 5.430, scaled = True) - recipe.restrain("delta2_si", lb = 3.54, ub = 3.54, scaled = True) - recipe.restrain("Biso_0_si", lb = 0.645, ub = 0.645, scaled = True) + recipe.restrain("a_si", lb=5.430, ub=5.430, scaled=True) + recipe.restrain("delta2_si", lb=3.54, ub=3.54, scaled=True) + recipe.restrain("Biso_0_si", lb=0.645, ub=0.645, scaled=True) # Give the recipe away so it can be used! return recipe + def plotResults(recipe): """Plot the results contained within a refined FitRecipe.""" @@ -148,10 +146,11 @@ def plotResults(recipe): diff = g - gcalc + diffzero import pylab - pylab.plot(r,g,'bo',label="G(r) Data") - pylab.plot(r, gcalc,'r-',label="G(r) Fit") - pylab.plot(r,diff,'g-',label="G(r) diff") - pylab.plot(r,diffzero,'k-') + + pylab.plot(r, g, "bo", label="G(r) Data") + pylab.plot(r, gcalc, "r-", label="G(r) Fit") + pylab.plot(r, diff, "g-", label="G(r) diff") + pylab.plot(r, diffzero, "k-") pylab.xlabel(r"$r (\AA)$") pylab.ylabel(r"$G (\AA^{-2})$") pylab.legend(loc=1) diff --git a/doc/examples/data/ni.iq b/doc/examples/data/ni.iq index 917301a1..56594ba3 100644 --- a/doc/examples/data/ni.iq +++ b/doc/examples/data/ni.iq @@ -2462,4 +2462,3 @@ 26.123511 0 26.133371 0 26.143228 0 - diff --git a/doc/examples/debyemodel.py b/doc/examples/debyemodel.py index 79bf7add..abdcd169 100644 --- a/doc/examples/debyemodel.py +++ b/doc/examples/debyemodel.py @@ -34,11 +34,10 @@ """ import numpy - -from diffpy.srfit.fitbase import FitContribution, FitRecipe, Profile, FitResults - from gaussianrecipe import scipyOptimize +from diffpy.srfit.fitbase import FitContribution, FitRecipe, FitResults, Profile + # The data data = """\ 015.0 0.00334 0.00013 @@ -56,6 +55,7 @@ ####### Example Code + def makeRecipe(): """Make the recipe for the fit. @@ -86,7 +86,7 @@ def makeRecipe(): # Load data and add it to the profile. It is our responsibility to get our # data into the profile. - xydy = numpy.array(map(float, data.split()), dtype=float).reshape(-1,3) + xydy = numpy.array(map(float, data.split()), dtype=float).reshape(-1, 3) x, y, dy = numpy.hsplit(xydy, 3) profile.setObservedProfile(x, y, dy) @@ -146,11 +146,12 @@ def makeRecipe(): # breaking the restraint by the point-average chi^2 value so that the # restraint is roughly as significant as any other data point throughout # the fit. - recipe.restrain(recipe.offset, lb = 0, scaled = True) + recipe.restrain(recipe.offset, lb=0, scaled=True) # We're done setting up the recipe. We can now do other things with it. return recipe + def plotResults(recipe): """Plot the results contained within a refined FitRecipe.""" @@ -163,15 +164,17 @@ def plotResults(recipe): Ucalc = recipe.pb.profile.ycalc import pylab - pylab.plot(T,U,'o',label="Pb $U_{iso}$ Data") - pylab.plot(T,Ucalc) + + pylab.plot(T, U, "o", label="Pb $U_{iso}$ Data") + pylab.plot(T, Ucalc) pylab.xlabel("T (K)") pylab.ylabel(r"$U_{iso} (\AA^2)$") - pylab.legend(loc = (0.0,0.8)) + pylab.legend(loc=(0.0, 0.8)) pylab.show() return + def main(): """The workflow of creating, running and inspecting a fit.""" @@ -197,12 +200,14 @@ def main(): # as we treat them as if existing in some external library that we cannot # modify. + def debye(T, m, thetaD): """A wrapped version of 'adps' that can handle an array of T-values.""" y = numpy.array([adps(m, thetaD, x) for x in T]) return y -def adps(m,thetaD,T): + +def adps(m, thetaD, T): """Calculates atomic displacement factors within the Debye model = (3h^2/4 pi^2 m kB thetaD)(phi(thetaD/T)/(ThetaD/T) + 1/4) @@ -216,9 +221,9 @@ def adps(m,thetaD,T): Uiso -- float -- the thermal factor from the Debye recipe at temp T """ - h = 6.6260755e-34 # Planck's constant. J.s of m^2.kg/s + h = 6.6260755e-34 # Planck's constant. J.s of m^2.kg/s kB = 1.3806503e-23 # Boltzmann's constant. J/K - amu = 1.66053886e-27 # Atomic mass unit. kg + amu = 1.66053886e-27 # Atomic mass unit. kg def __phi(x): """evaluates the phi integral needed in Debye calculation @@ -232,26 +237,24 @@ def __phi(x): phi -- float -- value of the phi function """ - def __debyeKernel(xi): - """function needed by debye calculators - """ - y = xi/(numpy.exp(xi)-1) + def __debyeKernel(xi): + """function needed by debye calculators""" + y = xi / (numpy.exp(xi) - 1) return y import scipy.integrate int = scipy.integrate.quad(__debyeKernel, 0, x) - phi = (1/x) * int[0] + phi = (1 / x) * int[0] return phi - m = m * amu - u2 = (3*h**2 / (4 * numpy.pi**2 *m *kB *thetaD))*\ - (__phi(thetaD/T)/(thetaD/T) + 1./4.) + u2 = (3 * h**2 / (4 * numpy.pi**2 * m * kB * thetaD)) * (__phi(thetaD / T) / (thetaD / T) + 1.0 / 4.0) + + return u2 * 1e20 - return u2*1e20 if __name__ == "__main__": diff --git a/doc/examples/debyemodelII.py b/doc/examples/debyemodelII.py index 0e5e3542..fcfa841d 100644 --- a/doc/examples/debyemodelII.py +++ b/doc/examples/debyemodelII.py @@ -34,12 +34,13 @@ done. """ -from diffpy.srfit.fitbase import FitRecipe, FitResults - from debyemodel import makeRecipe, scipyOptimize +from diffpy.srfit.fitbase import FitRecipe, FitResults + ####### Example Code + def makeRecipeII(): """Make a recipe for fitting low and high temperature regions. @@ -81,8 +82,8 @@ def makeRecipeII(): # Vary the offset from each FitContribution separately, while keeping the # Debye temperatures the same. We give each offset variable a different # name in the recipe so it retains its identity. - recipe.addVar(recipe.lowT.offset, name = "lowToffset") - recipe.addVar(recipe.highT.offset, name = "highToffset") + recipe.addVar(recipe.lowT.offset, name="lowToffset") + recipe.addVar(recipe.highT.offset, name="highToffset") # We create a new Variable and use the recipe's "constrain" method to # associate the Debye temperature parameters with that variable. recipe.newVar("thetaD", 100) @@ -90,6 +91,7 @@ def makeRecipeII(): recipe.constrain(recipe.highT.thetaD, "thetaD") return recipe + def plotResults(recipe): """Display the results contained within a refined FitRecipe.""" @@ -99,8 +101,8 @@ def plotResults(recipe): # We want to extend the fitting range to its full extent so we can get a # nice full plot. - recipe.lowT.profile.setCalculationRange(xmin='obs', xmax='obs') - recipe.highT.profile.setCalculationRange(xmin='obs', xmax='obs') + recipe.lowT.profile.setCalculationRange(xmin="obs", xmax="obs") + recipe.highT.profile.setCalculationRange(xmin="obs", xmax="obs") T = recipe.lowT.profile.x U = recipe.lowT.profile.y # We can use a FitContribution's 'evaluateEquation' method to evaluate @@ -114,18 +116,20 @@ def plotResults(recipe): # Now we can plot this. import pylab - pylab.plot(T,U,'o',label="Pb $U_{iso}$ Data") - lbl1 = r"$T_d$=%3.1f K, lowToff=%1.5f $\AA^2$"% (abs(thetaD),lowToffset) - lbl2 = r"$T_d$=%3.1f K, highToff=%1.5f $\AA^2$"% (abs(thetaD),highToffset) - pylab.plot(T,lowU,label=lbl1) - pylab.plot(T,highU,label=lbl2) + + pylab.plot(T, U, "o", label="Pb $U_{iso}$ Data") + lbl1 = r"$T_d$=%3.1f K, lowToff=%1.5f $\AA^2$" % (abs(thetaD), lowToffset) + lbl2 = r"$T_d$=%3.1f K, highToff=%1.5f $\AA^2$" % (abs(thetaD), highToffset) + pylab.plot(T, lowU, label=lbl1) + pylab.plot(T, highU, label=lbl2) pylab.xlabel("T (K)") pylab.ylabel(r"$U_{iso} (\AA^2)$") - pylab.legend(loc = (0.0,0.8)) + pylab.legend(loc=(0.0, 0.8)) pylab.show() return + def main(): # Create the recipe diff --git a/doc/examples/ellipsoidsas.py b/doc/examples/ellipsoidsas.py index 87c4d016..430f964a 100644 --- a/doc/examples/ellipsoidsas.py +++ b/doc/examples/ellipsoidsas.py @@ -16,14 +16,14 @@ """Example of a refinement of SAS I(Q) data to an ellipsoidal model. """ -from diffpy.srfit.sas import SASGenerator, SASParser -from diffpy.srfit.fitbase import FitContribution, FitRecipe -from diffpy.srfit.fitbase import FitResults, Profile - from gaussianrecipe import scipyOptimize +from diffpy.srfit.fitbase import FitContribution, FitRecipe, FitResults, Profile +from diffpy.srfit.sas import SASGenerator, SASParser + ####### Example Code + def makeRecipe(datname): """Create a fitting recipe for ellipsoidal SAS data.""" @@ -45,6 +45,7 @@ def makeRecipe(datname): # data. The documentation for the various sas models can be found at # http://www.sasview.org. from sas.models.EllipsoidModel import EllipsoidModel + model = EllipsoidModel() generator = SASGenerator("generator", model) @@ -53,7 +54,7 @@ def makeRecipe(datname): # before. contribution = FitContribution("ellipsoid") contribution.addProfileGenerator(generator) - contribution.setProfile(profile, xname = "q") + contribution.setProfile(profile, xname="q") # We want to fit the log of the signal to the log of the data so that the # higher-Q information remains significant. There are no I(Q) uncertainty @@ -81,6 +82,7 @@ def makeRecipe(datname): # Give the recipe away so it can be used! return recipe + def plotResults(recipe): """Plot the results contained within a refined FitRecipe.""" @@ -91,9 +93,10 @@ def plotResults(recipe): diff = y - ycalc + min(y) import pylab - pylab.loglog(r,y,'bo',label="I(Q) Data") - pylab.loglog(r, ycalc,'r-',label="I(Q) Fit") - pylab.loglog(r,diff,'g-',label="I(Q) diff") + + pylab.loglog(r, y, "bo", label="I(Q) Data") + pylab.loglog(r, ycalc, "r-", label="I(Q) Fit") + pylab.loglog(r, diff, "g-", label="I(Q) diff") pylab.xlabel(r"$Q (\AA^{-1})$") pylab.ylabel("$I (arb. units)$") pylab.legend(loc=1) @@ -101,6 +104,7 @@ def plotResults(recipe): pylab.show() return + if __name__ == "__main__": # Make the data and the recipe diff --git a/doc/examples/gaussiangenerator.py b/doc/examples/gaussiangenerator.py index 7b0818b8..cdf0a7fa 100644 --- a/doc/examples/gaussiangenerator.py +++ b/doc/examples/gaussiangenerator.py @@ -41,11 +41,11 @@ from numpy import exp -from diffpy.srfit.fitbase import ProfileGenerator, Profile -from diffpy.srfit.fitbase import FitContribution, FitRecipe +from diffpy.srfit.fitbase import FitContribution, FitRecipe, Profile, ProfileGenerator ####### Example Code + class GaussianGenerator(ProfileGenerator): """A class for calculating a Gaussian profile. @@ -86,9 +86,9 @@ def __init__(self, name): # ProfileGenerator. The signature is # _newParameter(name, value). # See the API for full details. - self._newParameter('A', 1.0) - self._newParameter('x0', 0.0) - self._newParameter('sigma', 1.0) + self._newParameter("A", 1.0) + self._newParameter("x0", 0.0) + self._newParameter("sigma", 1.0) return def __call__(self, x): @@ -107,13 +107,15 @@ def __call__(self, x): # Now we can use them. Note that we imported exp from numpy at the top # of the module. - y = A * exp(-0.5*(x-x0)**2/sigma**2) + y = A * exp(-0.5 * (x - x0) ** 2 / sigma**2) # Now return the value. return y + # End class GaussianGenerator + def makeRecipe(): """Create a recipe that uses the GaussianGenerator. @@ -159,7 +161,7 @@ def makeRecipe(): # gaussianrecipe.py so we can expect the same output. recipe.addVar(generator.A, 1) recipe.addVar(generator.x0, 5) - recipe.addVar(generator.sigma, name = "sig") + recipe.addVar(generator.sigma, name="sig") recipe.sig.value = 1 # Give the recipe away so it can be used! @@ -171,6 +173,7 @@ def makeRecipe(): # We can use main from gaussianrecipe.py, since this doesn't care if we use # a ProfileGenerator or not. from gaussianrecipe import main + main() # End of file diff --git a/doc/examples/gaussianrecipe.py b/doc/examples/gaussianrecipe.py index b4bb404d..7e1ed938 100644 --- a/doc/examples/gaussianrecipe.py +++ b/doc/examples/gaussianrecipe.py @@ -46,10 +46,11 @@ from __future__ import print_function -from diffpy.srfit.fitbase import FitContribution, FitRecipe, Profile, FitResults +from diffpy.srfit.fitbase import FitContribution, FitRecipe, FitResults, Profile ####### Example Code + def main(): """The workflow of creating, running and inspecting a fit.""" @@ -150,11 +151,12 @@ def makeRecipe(): # Here we create a Variable named 'sig', which is tied to the 'sigma' # Parameter of our FitContribution. We give it an initial value through the # FitRecipe instance. - recipe.addVar(contribution.sigma, name = "sig") + recipe.addVar(contribution.sigma, name="sig") recipe.sig.value = 1 return recipe + def scipyOptimize(recipe): """Optimize the recipe created above using scipy. @@ -169,11 +171,13 @@ def scipyOptimize(recipe): # (recipe.residual) and the starting values of the Variables # (recipe.getValues()). from scipy.optimize.minpack import leastsq + print("Fit using scipy's LM optimizer") leastsq(recipe.residual, recipe.getValues()) return + def plotResults(recipe): """Plot the results contained within a refined FitRecipe.""" @@ -189,15 +193,17 @@ def plotResults(recipe): # This stuff is specific to pylab from the matplotlib distribution. import pylab - pylab.plot(x, y, 'b.', label = "observed Gaussian") - pylab.plot(x, ycalc, 'g-', label = "calculated Gaussian") - pylab.legend(loc = (0.0,0.8)) + + pylab.plot(x, y, "b.", label="observed Gaussian") + pylab.plot(x, ycalc, "g-", label="calculated Gaussian") + pylab.legend(loc=(0.0, 0.8)) pylab.xlabel("x") pylab.ylabel("y") pylab.show() return + if __name__ == "__main__": main() diff --git a/doc/examples/interface.py b/doc/examples/interface.py index 106af7a2..1f33ad4e 100644 --- a/doc/examples/interface.py +++ b/doc/examples/interface.py @@ -19,10 +19,11 @@ the diffpy.srfit.interface.interface.py module. """ -from diffpy.srfit.fitbase import FitContribution, FitRecipe, Profile, FitResults +from diffpy.srfit.fitbase import FitContribution, FitRecipe, FitResults, Profile ####### Example Code + def main(): p = Profile() @@ -47,11 +48,12 @@ def main(): # loosely tying parameters to a value. r = FitRecipe() r |= c - r += (c.A, 0.5), (c.x0, 5), 'sig' - r *= c.sigma, 'sig' + r += (c.A, 0.5), (c.x0, 5), "sig" + r *= c.sigma, "sig" r %= c.A, 0.5, 0.5 from gaussianrecipe import scipyOptimize + scipyOptimize(r) res = FitResults(r) @@ -59,6 +61,7 @@ def main(): res.printResults() # Plot the results. from gaussianrecipe import plotResults + plotResults(r) return diff --git a/doc/examples/npintensity.py b/doc/examples/npintensity.py index 91a2b55d..f4988e9a 100644 --- a/doc/examples/npintensity.py +++ b/doc/examples/npintensity.py @@ -45,16 +45,14 @@ from __future__ import print_function import numpy +from gaussianrecipe import scipyOptimize -from diffpy.srfit.fitbase import ProfileGenerator, Profile -from diffpy.srfit.fitbase import FitContribution, FitRecipe -from diffpy.srfit.fitbase import FitResults +from diffpy.srfit.fitbase import FitContribution, FitRecipe, FitResults, Profile, ProfileGenerator from diffpy.srfit.structure.diffpyparset import DiffpyStructureParSet -from gaussianrecipe import scipyOptimize - ####### Example Code + class IntensityGenerator(ProfileGenerator): """A class for calculating intensity using the Debye equation. @@ -136,6 +134,7 @@ def setStructure(self, strufile): """ # Load the structure from file from diffpy.structure import Structure + stru = Structure() stru.read(strufile) @@ -167,6 +166,7 @@ def __call__(self, q): print("iofq called", self.count) return iofq(self.phase.stru, q) + # End class IntensityGenerator @@ -200,7 +200,7 @@ def makeRecipe(strufile, datname): # use it in equations with this name. contribution = FitContribution("bucky") contribution.addProfileGenerator(generator) - contribution.setProfile(profile, xname = "q") + contribution.setProfile(profile, xname="q") # Now we're ready to define the fitting equation for the FitContribution. # We need to modify the intensity calculation, and we'll do that from @@ -233,8 +233,9 @@ def makeRecipe(strufile, datname): # function and registering it with the FitContribution. pi = numpy.pi exp = numpy.exp + def gaussian(q, q0, width): - return 1/(2*pi*width**2)**0.5 * exp(-0.5 * ((q-q0)/width)**2) + return 1 / (2 * pi * width**2) ** 0.5 * exp(-0.5 * ((q - q0) / width) ** 2) # This registers the python function and extracts the name and creates # Parameters from the arguments. @@ -294,6 +295,7 @@ def gaussian(q, q0, width): # Give the recipe away so it can be used! return recipe + def main(): # Make the data and the recipe @@ -315,14 +317,15 @@ def main(): # 'iofq' from the IntensityGenerator. rescount = recipe.fithooks[0].count calcount = recipe.bucky.I.count - footer = "iofq called %i%% of the time"%int(100.0*calcount/rescount) - res.printResults(footer = footer) + footer = "iofq called %i%% of the time" % int(100.0 * calcount / rescount) + res.printResults(footer=footer) # Plot! plotResults(recipe) return + def plotResults(recipe): """Plot the results contained within a refined FitRecipe.""" @@ -335,10 +338,11 @@ def plotResults(recipe): diff = I - Icalc import pylab - pylab.plot(q,I,'ob',label="I(Q) Data") - pylab.plot(q,Icalc,'r-',label="I(Q) Fit") - pylab.plot(q,diff,'g-',label="I(Q) diff") - pylab.plot(q,bkgd,'c-',label="Bkgd. Fit") + + pylab.plot(q, I, "ob", label="I(Q) Data") + pylab.plot(q, Icalc, "r-", label="I(Q) Fit") + pylab.plot(q, diff, "g-", label="I(Q) diff") + pylab.plot(q, bkgd, "c-", label="Bkgd. Fit") pylab.xlabel(r"$Q (\AA^{-1})$") pylab.ylabel("Intensity (arb. units)") pylab.legend(loc=1) @@ -371,9 +375,9 @@ def iofq(S, q): # The precision of distance measurements deltad = 1e-6 - dmult = int(1/deltad) + dmult = int(1 / deltad) deltau = deltad**2 - umult = int(1/deltau) + umult = int(1 / deltau) pairdict = {} elcount = {} @@ -395,11 +399,11 @@ def iofq(S, q): # Get the distance to the desired precision d = S.distance(i, j) - D = int(d*dmult) + D = int(d * dmult) # Get the DW factor to the same precision ss = S[i].Uisoequiv + S[j].Uisoequiv - SS = int(ss*umult) + SS = int(ss * umult) # Record the multiplicity of this pair key = (els[0], els[1], D, SS) @@ -439,6 +443,7 @@ def iofq(S, q): return y + def getXScatteringFactor(el, q): """Get the x-ray scattering factor for an element over the q range. @@ -447,15 +452,17 @@ def getXScatteringFactor(el, q): """ try: import cctbx.eltbx.xray_scattering as xray + wk1995 = xray.wk1995(el) g = wk1995.fetch() # at_stol - at sin(theta)/lambda = Q/(4*pi) - f = numpy.asarray( map( g.at_stol, q/(4*numpy.pi) ) ) + f = numpy.asarray(map(g.at_stol, q / (4 * numpy.pi))) return f except ImportError: return 1 -def makeData(strufile, q, datname, scale, a, Uiso, sig, bkgc, nl = 1): + +def makeData(strufile, q, datname, scale, a, Uiso, sig, bkgc, nl=1): """Make some fake data and save it to file. Make some data to fit. This uses iofq to calculate an intensity curve, and @@ -474,6 +481,7 @@ def makeData(strufile, q, datname, scale, a, Uiso, sig, bkgc, nl = 1): """ from diffpy.structure import Structure + S = Structure() S.read(strufile) @@ -487,11 +495,11 @@ def makeData(strufile, q, datname, scale, a, Uiso, sig, bkgc, nl = 1): # We want to broaden the peaks as well. This simulates instrument effects. q0 = q[len(q) // 2] - g = numpy.exp(-0.5*((q-q0)/sig)**2) - y = numpy.convolve(y, g, mode='same')/sum(g) + g = numpy.exp(-0.5 * ((q - q0) / sig) ** 2) + y = numpy.convolve(y, g, mode="same") / sum(g) # Add a polynomial background. - bkgd = (q + bkgc)**2 * (1.5*max(q) - q)**5 + bkgd = (q + bkgc) ** 2 * (1.5 * max(q) - q) ** 5 bkgd *= 0.2 * max(y) / max(bkgd) y += bkgd @@ -500,11 +508,11 @@ def makeData(strufile, q, datname, scale, a, Uiso, sig, bkgc, nl = 1): y *= scale # Calculate the uncertainty - u = (y/nl)**0.5 + u = (y / nl) ** 0.5 # And apply the noise if nl > 0: - y = numpy.random.poisson(y*nl) / nl + y = numpy.random.poisson(y * nl) / nl # Now save it numpy.savetxt(datname, numpy.transpose([q, y, u])) diff --git a/doc/examples/npintensityII.py b/doc/examples/npintensityII.py index 7ab98dce..27623c3c 100644 --- a/doc/examples/npintensityII.py +++ b/doc/examples/npintensityII.py @@ -35,15 +35,14 @@ """ import numpy - -from diffpy.srfit.fitbase import FitContribution, FitRecipe, Profile, FitResults -from npintensity import IntensityGenerator -from npintensity import makeData - from gaussianrecipe import scipyOptimize +from npintensity import IntensityGenerator, makeData + +from diffpy.srfit.fitbase import FitContribution, FitRecipe, FitResults, Profile ####### Example Code + def makeRecipe(strufile, datname1, datname2): """Create a recipe that uses the IntensityGenerator. @@ -85,10 +84,10 @@ def makeRecipe(strufile, datname1, datname2): # Create the FitContributions. contribution1 = FitContribution("bucky1") contribution1.addProfileGenerator(generator1) - contribution1.setProfile(profile1, xname = "q") + contribution1.setProfile(profile1, xname="q") contribution2 = FitContribution("bucky2") contribution2.addProfileGenerator(generator2) - contribution2.setProfile(profile2, xname = "q") + contribution2.setProfile(profile2, xname="q") # Now we're ready to define the fitting equation for each FitContribution. # The functions registered below will be independent, even though they take @@ -105,8 +104,9 @@ def makeRecipe(strufile, datname1, datname2): # We will create the broadening function by registering a python function. pi = numpy.pi exp = numpy.exp + def gaussian(q, q0, width): - return 1/(2*pi*width**2)**0.5 * exp(-0.5 * ((q-q0)/width)**2) + return 1 / (2 * pi * width**2) ** 0.5 * exp(-0.5 * ((q - q0) / width) ** 2) contribution1.registerFunction(gaussian) contribution2.registerFunction(gaussian) @@ -128,32 +128,32 @@ def gaussian(q, q0, width): # background that we just defined in the FitContributions. We have to do # this separately for each FitContribution. We tag the variables so it is # easy to retrieve the background variables. - recipe.addVar(contribution1.b0, 0, name = "b1_0", tag = "bcoeffs1") - recipe.addVar(contribution1.b1, 0, name = "b1_1", tag = "bcoeffs1") - recipe.addVar(contribution1.b2, 0, name = "b1_2", tag = "bcoeffs1") - recipe.addVar(contribution1.b3, 0, name = "b1_3", tag = "bcoeffs1") - recipe.addVar(contribution1.b4, 0, name = "b1_4", tag = "bcoeffs1") - recipe.addVar(contribution1.b5, 0, name = "b1_5", tag = "bcoeffs1") - recipe.addVar(contribution1.b6, 0, name = "b1_6", tag = "bcoeffs1") - recipe.addVar(contribution1.b7, 0, name = "b1_7", tag = "bcoeffs1") - recipe.addVar(contribution1.b8, 0, name = "b1_8", tag = "bcoeffs1") - recipe.addVar(contribution1.b9, 0, name = "b1_9", tag = "bcoeffs1") - recipe.addVar(contribution2.b0, 0, name = "b2_0", tag = "bcoeffs2") - recipe.addVar(contribution2.b1, 0, name = "b2_1", tag = "bcoeffs2") - recipe.addVar(contribution2.b2, 0, name = "b2_2", tag = "bcoeffs2") - recipe.addVar(contribution2.b3, 0, name = "b2_3", tag = "bcoeffs2") - recipe.addVar(contribution2.b4, 0, name = "b2_4", tag = "bcoeffs2") - recipe.addVar(contribution2.b5, 0, name = "b2_5", tag = "bcoeffs2") - recipe.addVar(contribution2.b6, 0, name = "b2_6", tag = "bcoeffs2") - recipe.addVar(contribution2.b7, 0, name = "b2_7", tag = "bcoeffs2") - recipe.addVar(contribution2.b8, 0, name = "b2_8", tag = "bcoeffs2") - recipe.addVar(contribution2.b9, 0, name = "b2_9", tag = "bcoeffs2") + recipe.addVar(contribution1.b0, 0, name="b1_0", tag="bcoeffs1") + recipe.addVar(contribution1.b1, 0, name="b1_1", tag="bcoeffs1") + recipe.addVar(contribution1.b2, 0, name="b1_2", tag="bcoeffs1") + recipe.addVar(contribution1.b3, 0, name="b1_3", tag="bcoeffs1") + recipe.addVar(contribution1.b4, 0, name="b1_4", tag="bcoeffs1") + recipe.addVar(contribution1.b5, 0, name="b1_5", tag="bcoeffs1") + recipe.addVar(contribution1.b6, 0, name="b1_6", tag="bcoeffs1") + recipe.addVar(contribution1.b7, 0, name="b1_7", tag="bcoeffs1") + recipe.addVar(contribution1.b8, 0, name="b1_8", tag="bcoeffs1") + recipe.addVar(contribution1.b9, 0, name="b1_9", tag="bcoeffs1") + recipe.addVar(contribution2.b0, 0, name="b2_0", tag="bcoeffs2") + recipe.addVar(contribution2.b1, 0, name="b2_1", tag="bcoeffs2") + recipe.addVar(contribution2.b2, 0, name="b2_2", tag="bcoeffs2") + recipe.addVar(contribution2.b3, 0, name="b2_3", tag="bcoeffs2") + recipe.addVar(contribution2.b4, 0, name="b2_4", tag="bcoeffs2") + recipe.addVar(contribution2.b5, 0, name="b2_5", tag="bcoeffs2") + recipe.addVar(contribution2.b6, 0, name="b2_6", tag="bcoeffs2") + recipe.addVar(contribution2.b7, 0, name="b2_7", tag="bcoeffs2") + recipe.addVar(contribution2.b8, 0, name="b2_8", tag="bcoeffs2") + recipe.addVar(contribution2.b9, 0, name="b2_9", tag="bcoeffs2") # We also want to adjust the scale and the convolution width - recipe.addVar(contribution1.scale, 1, name = "scale1") - recipe.addVar(contribution1.width, 0.1, name = "width1") - recipe.addVar(contribution2.scale, 1, name = "scale2") - recipe.addVar(contribution2.width, 0.1, name = "width2") + recipe.addVar(contribution1.scale, 1, name="scale1") + recipe.addVar(contribution1.width, 0.1, name="width1") + recipe.addVar(contribution2.scale, 1, name="scale2") + recipe.addVar(contribution2.width, 0.1, name="width2") # We can also refine structural parameters. We only have to do this once, # since each generator holds the same DiffpyStructureParSet. @@ -175,6 +175,7 @@ def gaussian(q, q0, width): # Give the recipe away so it can be used! return recipe + def plotResults(recipe): """Plot the results contained within a refined FitRecipe.""" @@ -197,18 +198,19 @@ def plotResults(recipe): diff1 += offset import pylab + pylab.subplot(2, 1, 1) - pylab.plot(q,I1,'bo',label="I1(Q) Data") - pylab.plot(q,Icalc1,'r-',label="I1(Q) Fit") - pylab.plot(q,diff1,'g-',label="I1(Q) diff") - pylab.plot(q,bkgd1,'c-',label="Bkgd1 Fit") + pylab.plot(q, I1, "bo", label="I1(Q) Data") + pylab.plot(q, Icalc1, "r-", label="I1(Q) Fit") + pylab.plot(q, diff1, "g-", label="I1(Q) diff") + pylab.plot(q, bkgd1, "c-", label="Bkgd1 Fit") pylab.legend(loc=1) pylab.subplot(2, 1, 2) - pylab.plot(q,I2,'bo',label="I2(Q) Data") - pylab.plot(q,Icalc2,'r-',label="I2(Q) Fit") - pylab.plot(q,diff2,'g-',label="I2(Q) diff") - pylab.plot(q,bkgd2,'c-',label="Bkgd2 Fit") + pylab.plot(q, I2, "bo", label="I2(Q) Data") + pylab.plot(q, Icalc2, "r-", label="I2(Q) Fit") + pylab.plot(q, diff2, "g-", label="I2(Q) diff") + pylab.plot(q, bkgd2, "c-", label="Bkgd2 Fit") pylab.xlabel(r"$Q (\AA^{-1})$") pylab.ylabel("Intensity (arb. units)") pylab.legend(loc=1) @@ -216,6 +218,7 @@ def plotResults(recipe): pylab.show() return + def main(): # Make two different data sets, each from the same structure, but with @@ -258,6 +261,7 @@ def main(): return + if __name__ == "__main__": main() diff --git a/doc/examples/nppdfcrystal.py b/doc/examples/nppdfcrystal.py index 46ffb848..d637f9e1 100644 --- a/doc/examples/nppdfcrystal.py +++ b/doc/examples/nppdfcrystal.py @@ -26,15 +26,12 @@ """ import numpy - +from gaussianrecipe import scipyOptimize from pyobjcryst import loadCrystal +from diffpy.srfit.fitbase import FitContribution, FitRecipe, FitResults, Profile from diffpy.srfit.pdf import PDFGenerator, PDFParser -from diffpy.srfit.fitbase import Profile -from diffpy.srfit.fitbase import FitContribution, FitRecipe -from diffpy.srfit.fitbase import FitResults -from gaussianrecipe import scipyOptimize def makeRecipe(ciffile, grdata): """Make a recipe to model a crystal-like nanoparticle PDF.""" @@ -45,10 +42,10 @@ def makeRecipe(ciffile, grdata): pdfparser = PDFParser() pdfparser.parseFile(grdata) pdfprofile.loadParsedData(pdfparser) - pdfprofile.setCalculationRange(xmin = 0.1, xmax = 20) + pdfprofile.setCalculationRange(xmin=0.1, xmax=20) pdfcontribution = FitContribution("pdf") - pdfcontribution.setProfile(pdfprofile, xname = "r") + pdfcontribution.setProfile(pdfprofile, xname="r") pdfgenerator = PDFGenerator("G") pdfgenerator.setQmax(30.0) @@ -58,7 +55,8 @@ def makeRecipe(ciffile, grdata): # Register the nanoparticle shape factor. from diffpy.srfit.pdf.characteristicfunctions import sphericalCF - pdfcontribution.registerFunction(sphericalCF, name = "f") + + pdfcontribution.registerFunction(sphericalCF, name="f") # Now we set up the fitting equation. pdfcontribution.setEquation("f * G") @@ -79,6 +77,7 @@ def makeRecipe(ciffile, grdata): return recipe + def plotResults(recipe): """Plot the results contained within a refined FitRecipe.""" @@ -96,12 +95,13 @@ def plotResults(recipe): fr *= max(g) / fr[0] import pylab - pylab.plot(r,g,'bo',label="G(r) Data") - pylab.plot(r, gcryst,'y--',label="G(r) Crystal") - pylab.plot(r, fr,'k--',label="f(r) calculated (scaled)") - pylab.plot(r, gcalc,'r-',label="G(r) Fit") - pylab.plot(r,diff,'g-',label="G(r) diff") - pylab.plot(r, diffzero,'k-') + + pylab.plot(r, g, "bo", label="G(r) Data") + pylab.plot(r, gcryst, "y--", label="G(r) Crystal") + pylab.plot(r, fr, "k--", label="f(r) calculated (scaled)") + pylab.plot(r, gcalc, "r-", label="G(r) Fit") + pylab.plot(r, diff, "g-", label="G(r) diff") + pylab.plot(r, diffzero, "k-") pylab.xlabel(r"$r (\AA)$") pylab.ylabel(r"$G (\AA^{-2})$") pylab.legend(loc=1) @@ -109,6 +109,7 @@ def plotResults(recipe): pylab.show() return + if __name__ == "__main__": ciffile = "data/pb.cif" diff --git a/doc/examples/nppdfobjcryst.py b/doc/examples/nppdfobjcryst.py index bab460fc..472f6460 100644 --- a/doc/examples/nppdfobjcryst.py +++ b/doc/examples/nppdfobjcryst.py @@ -21,13 +21,12 @@ import numpy -from diffpy.srfit.fitbase import Profile -from diffpy.srfit.fitbase import FitContribution, FitRecipe -from diffpy.srfit.fitbase import FitResults +from diffpy.srfit.fitbase import FitContribution, FitRecipe, FitResults, Profile from diffpy.srfit.pdf import DebyePDFGenerator ####### Example Code + def makeRecipe(molecule, datname): """Create a recipe that uses the DebyePDFGenerator.""" @@ -49,7 +48,7 @@ def makeRecipe(molecule, datname): ## The FitContribution contribution = FitContribution("bucky") contribution.addProfileGenerator(generator) - contribution.setProfile(profile, xname = "r") + contribution.setProfile(profile, xname="r") # Make a FitRecipe. recipe = FitRecipe() @@ -92,7 +91,7 @@ def makeRecipe(molecule, datname): # This creates a Parameter that moves the second atom according to the # bond length. Note that each Parameter needs a unique name. - par = c60.addBondLengthParameter("rad%i"%i, center, atom) + par = c60.addBondLengthParameter("rad%i" % i, center, atom) recipe.constrain(par, radius) # Add the correlation term, scale. The scale is too short to effectively @@ -103,6 +102,7 @@ def makeRecipe(molecule, datname): # Give the recipe away so it can be used! return recipe + def plotResults(recipe): """Plot the results contained within a refined FitRecipe.""" @@ -110,14 +110,15 @@ def plotResults(recipe): r = recipe.bucky.profile.x g = recipe.bucky.profile.y gcalc = recipe.bucky.profile.ycalc - diffzero = -0.8 * max(g) * numpy.ones_like(g) + diffzero = -0.8 * max(g) * numpy.ones_like(g) diff = g - gcalc + diffzero import pylab - pylab.plot(r,g,'ob',label="G(r) Data") - pylab.plot(r,gcalc,'-r',label="G(r) Fit") - pylab.plot(r,diff,'-g',label="G(r) diff") - pylab.plot(r,diffzero,'-k') + + pylab.plot(r, g, "ob", label="G(r) Data") + pylab.plot(r, gcalc, "-r", label="G(r) Fit") + pylab.plot(r, diff, "-g", label="G(r) diff") + pylab.plot(r, diffzero, "-k") pylab.xlabel(r"$r (\AA)$") pylab.ylabel(r"$G (\AA^{-2})$") pylab.legend(loc=1) @@ -125,6 +126,7 @@ def plotResults(recipe): pylab.show() return + def main(): molecule = makeC60() @@ -135,6 +137,7 @@ def main(): # Optimize from scipy.optimize import leastsq + leastsq(recipe.residual, recipe.getValues()) # Print results @@ -146,8 +149,8 @@ def main(): return -c60xyz = \ -""" + +c60xyz = """ 3.451266498 0.685000000 0.000000000 3.451266498 -0.685000000 0.000000000 -3.451266498 0.685000000 0.000000000 @@ -210,6 +213,7 @@ def main(): -2.279809890 -2.580456608 -0.724000000 """ + def makeC60(): """Make the C60 molecule using pyobjcryst.""" @@ -236,7 +240,7 @@ def makeC60(): # Add the other atoms. They will be named C1, C2, ..., C60. for i, l in enumerate(c60xyz.strip().splitlines()): x, y, z = map(float, l.split()) - m.AddAtom(x, y, z, sp, "C%i"%(i+1)) + m.AddAtom(x, y, z, sp, "C%i" % (i + 1)) return m diff --git a/doc/examples/nppdfsas.py b/doc/examples/nppdfsas.py index b5975345..2a4a8543 100644 --- a/doc/examples/nppdfsas.py +++ b/doc/examples/nppdfsas.py @@ -24,17 +24,14 @@ """ import numpy - +from gaussianrecipe import scipyOptimize from pyobjcryst import loadCrystal +from diffpy.srfit.fitbase import FitContribution, FitRecipe, FitResults, Profile from diffpy.srfit.pdf import PDFGenerator, PDFParser from diffpy.srfit.pdf.characteristicfunctions import SASCF -from diffpy.srfit.sas import SASParser, SASGenerator -from diffpy.srfit.fitbase import Profile -from diffpy.srfit.fitbase import FitContribution, FitRecipe -from diffpy.srfit.fitbase import FitResults +from diffpy.srfit.sas import SASGenerator, SASParser -from gaussianrecipe import scipyOptimize def makeRecipe(ciffile, grdata, iqdata): """Make complex-modeling recipe where I(q) and G(r) are fit @@ -50,10 +47,10 @@ def makeRecipe(ciffile, grdata, iqdata): pdfparser = PDFParser() pdfparser.parseFile(grdata) pdfprofile.loadParsedData(pdfparser) - pdfprofile.setCalculationRange(xmin = 0.1, xmax = 20) + pdfprofile.setCalculationRange(xmin=0.1, xmax=20) pdfcontribution = FitContribution("pdf") - pdfcontribution.setProfile(pdfprofile, xname = "r") + pdfcontribution.setProfile(pdfprofile, xname="r") pdfgenerator = PDFGenerator("G") pdfgenerator.setQmax(30.0) @@ -75,6 +72,7 @@ def makeRecipe(ciffile, grdata, iqdata): sascontribution.setProfile(sasprofile) from sas.models.EllipsoidModel import EllipsoidModel + model = EllipsoidModel() sasgenerator = SASGenerator("generator", model) sascontribution.addProfileGenerator(sasgenerator) @@ -105,7 +103,7 @@ def makeRecipe(ciffile, grdata, iqdata): recipe.addVar(pdfgenerator.delta2, 0) # SAS - recipe.addVar(sasgenerator.scale, 1, name = "iqscale") + recipe.addVar(sasgenerator.scale, 1, name="iqscale") recipe.addVar(sasgenerator.radius_a, 10) recipe.addVar(sasgenerator.radius_b, 10) @@ -117,16 +115,17 @@ def makeRecipe(ciffile, grdata, iqdata): return recipe + def fitRecipe(recipe): """We refine in stages to help the refinement converge.""" # Tune SAS. recipe.setWeight(recipe.pdf, 0) recipe.fix("all") - recipe.free("radius_a", "radius_b", iqscale = 1e8) - recipe.constrain('radius_b', 'radius_a') + recipe.free("radius_a", "radius_b", iqscale=1e8) + recipe.constrain("radius_b", "radius_a") scipyOptimize(recipe) - recipe.unconstrain('radius_b') + recipe.unconstrain("radius_b") # Tune PDF recipe.setWeight(recipe.pdf, 1) @@ -143,6 +142,7 @@ def fitRecipe(recipe): return + def plotResults(recipe): """Plot the results contained within a refined FitRecipe.""" @@ -160,12 +160,13 @@ def plotResults(recipe): fr *= max(g) / fr[0] import pylab - pylab.plot(r,g,'bo',label="G(r) Data") - pylab.plot(r, gcryst,'y--',label="G(r) Crystal") - pylab.plot(r, fr,'k--',label="f(r) calculated (scaled)") - pylab.plot(r, gcalc,'r-',label="G(r) Fit") - pylab.plot(r, diff,'g-',label="G(r) diff") - pylab.plot(r, diffzero,'k-') + + pylab.plot(r, g, "bo", label="G(r) Data") + pylab.plot(r, gcryst, "y--", label="G(r) Crystal") + pylab.plot(r, fr, "k--", label="f(r) calculated (scaled)") + pylab.plot(r, gcalc, "r-", label="G(r) Fit") + pylab.plot(r, diff, "g-", label="G(r) diff") + pylab.plot(r, diffzero, "k-") pylab.xlabel(r"$r (\AA)$") pylab.ylabel(r"$G (\AA^{-2})$") pylab.legend(loc=1) diff --git a/doc/examples/simplepdf.py b/doc/examples/simplepdf.py index df95bbd2..bbea1b56 100644 --- a/doc/examples/simplepdf.py +++ b/doc/examples/simplepdf.py @@ -19,22 +19,23 @@ It uses the PDFContribution class to simplify fit setup. """ -from diffpy.structure import Structure -from diffpy.srfit.pdf import PDFContribution -from diffpy.srfit.fitbase import FitRecipe, FitResults - -from gaussianrecipe import scipyOptimize from crystalpdf import plotResults +from gaussianrecipe import scipyOptimize + +from diffpy.srfit.fitbase import FitRecipe, FitResults +from diffpy.srfit.pdf import PDFContribution +from diffpy.structure import Structure ####### Example Code + def makeRecipe(ciffile, datname): """Create a fitting recipe for crystalline PDF data.""" # Work directly with a custom PDFContribution to load the data contribution = PDFContribution("nickel") contribution.loadData(datname) - contribution.setCalculationRange(xmin = 1, xmax = 20, dx = 0.1) + contribution.setCalculationRange(xmin=1, xmax=20, dx=0.1) # and the phase stru = Structure() @@ -49,6 +50,7 @@ def makeRecipe(ciffile, datname): phase = contribution.nickel.phase from diffpy.srfit.structure import constrainAsSpaceGroup + sgpars = constrainAsSpaceGroup(phase, "Fm-3m") for par in sgpars.latpars: @@ -57,12 +59,13 @@ def makeRecipe(ciffile, datname): recipe.addVar(par, 0.005) recipe.addVar(contribution.scale, 1) - recipe.addVar(contribution.qdamp, 0.03, fixed = True) + recipe.addVar(contribution.qdamp, 0.03, fixed=True) recipe.addVar(contribution.nickel.delta2, 5) # Give the recipe away so it can be used! return recipe + if __name__ == "__main__": # Make the data and the recipe diff --git a/doc/examples/simplepdftwophase.py b/doc/examples/simplepdftwophase.py index f000926a..b6a663eb 100644 --- a/doc/examples/simplepdftwophase.py +++ b/doc/examples/simplepdftwophase.py @@ -15,23 +15,23 @@ """Example of a simplified PDF refinement of two-phase structure.""" +from crystalpdftwophase import plotResults +from gaussianrecipe import scipyOptimize from pyobjcryst import loadCrystal -from diffpy.srfit.pdf import PDFContribution from diffpy.srfit.fitbase import FitRecipe, FitResults - -from gaussianrecipe import scipyOptimize -from crystalpdftwophase import plotResults +from diffpy.srfit.pdf import PDFContribution ####### Example Code + def makeRecipe(niciffile, siciffile, datname): """Create a fitting recipe for crystalline PDF data.""" # Load data and add it to the profile contribution = PDFContribution("nisi") contribution.loadData(datname) - contribution.setCalculationRange(xmax = 20) + contribution.setCalculationRange(xmax=20) stru = loadCrystal(niciffile) contribution.addStructure("ni", stru) @@ -66,13 +66,13 @@ def makeRecipe(niciffile, siciffile, datname): # above. phase_ni = contribution.ni.phase for par in phase_ni.sgpars: - recipe.addVar(par, name = par.name + "_ni") - recipe.addVar(contribution.ni.delta2, name = "delta2_ni") + recipe.addVar(par, name=par.name + "_ni") + recipe.addVar(contribution.ni.delta2, name="delta2_ni") # Next the silicon parameters phase_si = contribution.si.phase for par in phase_si.sgpars: - recipe.addVar(par, name = par.name + "_si") - recipe.addVar(contribution.si.delta2, name = "delta2_si") + recipe.addVar(par, name=par.name + "_si") + recipe.addVar(contribution.si.delta2, name="delta2_si") # We have prior information from the earlier examples so we'll use it here # in the form of restraints. @@ -82,18 +82,18 @@ def makeRecipe(niciffile, siciffile, datname): # derived has no uncertainty. Thus, we will tell the recipe to scale the # residual, which means that it will be weighted as much as the average # data point during the fit. - recipe.restrain("a_ni", lb = 3.527, ub = 3.527, scaled = True) + recipe.restrain("a_ni", lb=3.527, ub=3.527, scaled=True) # Now we do the same with the delta2 and Biso parameters (remember that # Biso = 8*pi**2*Uiso) - recipe.restrain("delta2_ni", lb = 2.22, ub = 2.22, scaled = True) - recipe.restrain("Biso_0_ni", lb = 0.454, ub = 0.454, scaled = True) + recipe.restrain("delta2_ni", lb=2.22, ub=2.22, scaled=True) + recipe.restrain("Biso_0_ni", lb=0.454, ub=0.454, scaled=True) # # We can do the same with the silicon values. We haven't done a thorough # job of measuring the uncertainties in the results, so we'll scale these # as well. - recipe.restrain("a_si", lb = 5.430, ub = 5.430, scaled = True) - recipe.restrain("delta2_si", lb = 3.54, ub = 3.54, scaled = True) - recipe.restrain("Biso_0_si", lb = 0.645, ub = 0.645, scaled = True) + recipe.restrain("a_si", lb=5.430, ub=5.430, scaled=True) + recipe.restrain("delta2_si", lb=3.54, ub=3.54, scaled=True) + recipe.restrain("Biso_0_si", lb=0.645, ub=0.645, scaled=True) # Give the recipe away so it can be used! return recipe diff --git a/doc/examples/simplerecipe.py b/doc/examples/simplerecipe.py index 45b8785f..50a48696 100644 --- a/doc/examples/simplerecipe.py +++ b/doc/examples/simplerecipe.py @@ -24,6 +24,7 @@ ####### Example Code + def main(): """Set up a simple recipe in a few lines.""" @@ -46,6 +47,7 @@ def main(): # We explicitly optimize the residual method of the SimpleRecipe from scipy.optimize import leastsq + leastsq(recipe.residual, recipe.values) # Print the results @@ -53,6 +55,7 @@ def main(): return + if __name__ == "__main__": main() diff --git a/doc/examples/threedoublepeaks.py b/doc/examples/threedoublepeaks.py index 35b7597b..6e3ceea8 100644 --- a/doc/examples/threedoublepeaks.py +++ b/doc/examples/threedoublepeaks.py @@ -20,10 +20,11 @@ import numpy -from diffpy.srfit.fitbase import FitContribution, FitRecipe, Profile, FitResults +from diffpy.srfit.fitbase import FitContribution, FitRecipe, FitResults, Profile ####### Example Code + def makeRecipe(): """Make a FitRecipe for fitting three double-gaussian curves to data. @@ -48,15 +49,15 @@ def makeRecipe(): # Create the contribution contribution = FitContribution("peaks") - contribution.setProfile(profile, xname = "t") + contribution.setProfile(profile, xname="t") pi = numpy.pi exp = numpy.exp # This is a building-block of our profile function def gaussian(t, mu, sig): - return 1/(2*pi*sig**2)**0.5 * exp(-0.5 * ((t-mu)/sig)**2) + return 1 / (2 * pi * sig**2) ** 0.5 * exp(-0.5 * ((t - mu) / sig) ** 2) - contribution.registerFunction(gaussian, name = "peakshape") + contribution.registerFunction(gaussian, name="peakshape") def delta(t, mu): """Calculate a delta-function. @@ -83,10 +84,11 @@ def delta(t, mu): + 0.23*convolve( delta(t, mu22), peakshape(t, c, sig22) ) ) + \ A3 * ( convolve( delta(t, mu31), peakshape(t, c, sig31) ) \ + 0.23*convolve( delta(t, mu32), peakshape(t, c, sig32) ) ) + \ - bkgd") + bkgd" + ) # c is the center of the gaussian. - contribution.c.value = x[len(x) // 2] + contribution.c.value = x[len(x) // 2] ## The FitRecipe # The FitRecipe lets us define what we want to fit. It is where we can @@ -109,12 +111,13 @@ def delta(t, mu): recipe.addVar(contribution.mu31, 33.0) # Constrain the position of the second double peak - from numpy import sin, arcsin + from numpy import arcsin, sin + def peakloc(mu): """Calculate the location of the second peak given the first.""" l1 = 1.012 l2 = 1.0 - return 180 / pi * arcsin( pi / 180 * l2 * sin(mu) / l1 ) + return 180 / pi * arcsin(pi / 180 * l2 * sin(mu) / l1) recipe.registerFunction(peakloc) recipe.constrain(contribution.mu12, "peakloc(mu11)") @@ -128,7 +131,7 @@ def peakloc(mu): def sig(sig0, dsig, mu): """Calculate the peak broadening with respect to position.""" - return sig0 * (1 - dsig * mu**2); + return sig0 * (1 - dsig * mu**2) recipe.registerFunction(sig) recipe.fix("mu") @@ -136,25 +139,23 @@ def sig(sig0, dsig, mu): recipe.sig0.value = 0.001 recipe.dsig.value = 4.0 recipe.constrain(contribution.sig11, "sig(sig0, dsig, mu11)") - recipe.constrain(contribution.sig12, "sig(sig0, dsig, mu12)", - ns = {"mu12" : contribution.mu12} ) + recipe.constrain(contribution.sig12, "sig(sig0, dsig, mu12)", ns={"mu12": contribution.mu12}) recipe.constrain(contribution.sig21, "sig(sig0, dsig, mu21)") - recipe.constrain(contribution.sig22, "sig(sig0, dsig, mu22)", - ns = {"mu22" : contribution.mu22} ) + recipe.constrain(contribution.sig22, "sig(sig0, dsig, mu22)", ns={"mu22": contribution.mu22}) recipe.constrain(contribution.sig31, "sig(sig0, dsig, mu31)") - recipe.constrain(contribution.sig32, "sig(sig0, dsig, mu32)", - ns = {"mu32" : contribution.mu32} ) + recipe.constrain(contribution.sig32, "sig(sig0, dsig, mu32)", ns={"mu32": contribution.mu32}) # Also the background - recipe.addVar(contribution.b0, 0, tag = "bkgd") - recipe.addVar(contribution.b1, 0, tag = "bkgd") - recipe.addVar(contribution.b2, 0, tag = "bkgd") - recipe.addVar(contribution.b3, 0, tag = "bkgd") - recipe.addVar(contribution.b4, 0, tag = "bkgd") - recipe.addVar(contribution.b5, 0, tag = "bkgd") - recipe.addVar(contribution.b6, 0, tag = "bkgd") + recipe.addVar(contribution.b0, 0, tag="bkgd") + recipe.addVar(contribution.b1, 0, tag="bkgd") + recipe.addVar(contribution.b2, 0, tag="bkgd") + recipe.addVar(contribution.b3, 0, tag="bkgd") + recipe.addVar(contribution.b4, 0, tag="bkgd") + recipe.addVar(contribution.b5, 0, tag="bkgd") + recipe.addVar(contribution.b6, 0, tag="bkgd") return recipe + def scipyOptimize(recipe): """Optimize the recipe created above using scipy. @@ -169,6 +170,7 @@ def scipyOptimize(recipe): # (recipe.residual) and the starting values of the Variables # (recipe.getValues()). from scipy.optimize.minpack import leastsq + print("Fit using scipy's LM optimizer") leastsq(recipe.residual, recipe.getValues()) @@ -190,16 +192,18 @@ def plotResults(recipe): # This stuff is specific to pylab from the matplotlib distribution. import pylab - pylab.plot(x, y, 'b.', label = "observed profile") - pylab.plot(x, ycalc, 'r-', label = "calculated profile") - pylab.plot(x, y - ycalc - 0.1 * max(y), 'g-', label = "difference") - pylab.legend(loc = (0.0,0.8)) + + pylab.plot(x, y, "b.", label="observed profile") + pylab.plot(x, ycalc, "r-", label="calculated profile") + pylab.plot(x, y - ycalc - 0.1 * max(y), "g-", label="difference") + pylab.legend(loc=(0.0, 0.8)) pylab.xlabel("x") pylab.ylabel("y") pylab.show() return + def steerFit(recipe): """Steer the fit for this problem. @@ -219,6 +223,7 @@ def steerFit(recipe): return + if __name__ == "__main__": # Create the recipe diff --git a/doc/source/api/diffpy.srfit.equation.literals.rst b/doc/source/api/diffpy.srfit.equation.literals.rst index 6875b5ef..20679c3e 100644 --- a/doc/source/api/diffpy.srfit.equation.literals.rst +++ b/doc/source/api/diffpy.srfit.equation.literals.rst @@ -42,4 +42,3 @@ diffpy.srfit.equation.literals.operators module :members: :undoc-members: :show-inheritance: - diff --git a/doc/source/api/diffpy.srfit.equation.rst b/doc/source/api/diffpy.srfit.equation.rst index f7a47192..ef74cf23 100644 --- a/doc/source/api/diffpy.srfit.equation.rst +++ b/doc/source/api/diffpy.srfit.equation.rst @@ -35,4 +35,3 @@ diffpy.srfit.equation.equationmod module :members: :undoc-members: :show-inheritance: - diff --git a/doc/source/api/diffpy.srfit.equation.visitors.rst b/doc/source/api/diffpy.srfit.equation.visitors.rst index 54e10bc6..88c35374 100644 --- a/doc/source/api/diffpy.srfit.equation.visitors.rst +++ b/doc/source/api/diffpy.srfit.equation.visitors.rst @@ -50,4 +50,3 @@ diffpy.srfit.equation.visitors.printer module :members: :undoc-members: :show-inheritance: - diff --git a/doc/source/api/diffpy.srfit.fitbase.rst b/doc/source/api/diffpy.srfit.fitbase.rst index 5c092c9f..19bc255e 100644 --- a/doc/source/api/diffpy.srfit.fitbase.rst +++ b/doc/source/api/diffpy.srfit.fitbase.rst @@ -138,4 +138,3 @@ diffpy.srfit.fitbase.profileparser module :members: :undoc-members: :show-inheritance: - diff --git a/doc/source/api/diffpy.srfit.interface.rst b/doc/source/api/diffpy.srfit.interface.rst index 40b829d7..92497fea 100644 --- a/doc/source/api/diffpy.srfit.interface.rst +++ b/doc/source/api/diffpy.srfit.interface.rst @@ -18,4 +18,3 @@ diffpy.srfit.interface.interface module :members: :undoc-members: :show-inheritance: - diff --git a/doc/source/api/diffpy.srfit.pdf.rst b/doc/source/api/diffpy.srfit.pdf.rst index 60f3e947..424c7f16 100644 --- a/doc/source/api/diffpy.srfit.pdf.rst +++ b/doc/source/api/diffpy.srfit.pdf.rst @@ -58,4 +58,3 @@ diffpy.srfit.pdf.pdfcontribution module :members: :undoc-members: :show-inheritance: - diff --git a/doc/source/api/diffpy.srfit.rst b/doc/source/api/diffpy.srfit.rst index 9eef9e38..8f840d0c 100644 --- a/doc/source/api/diffpy.srfit.rst +++ b/doc/source/api/diffpy.srfit.rst @@ -32,4 +32,3 @@ diffpy.srfit.exceptions module :members: :undoc-members: :show-inheritance: - diff --git a/doc/source/api/diffpy.srfit.sas.rst b/doc/source/api/diffpy.srfit.sas.rst index fbc67925..8ad88d91 100644 --- a/doc/source/api/diffpy.srfit.sas.rst +++ b/doc/source/api/diffpy.srfit.sas.rst @@ -58,4 +58,3 @@ diffpy.srfit.sas.sasgenerator module :members: :undoc-members: :show-inheritance: - diff --git a/doc/source/api/diffpy.srfit.structure.rst b/doc/source/api/diffpy.srfit.structure.rst index 1fa5326d..59063abd 100644 --- a/doc/source/api/diffpy.srfit.structure.rst +++ b/doc/source/api/diffpy.srfit.structure.rst @@ -66,4 +66,3 @@ diffpy.srfit.structure.sgconstraints module :members: :undoc-members: :show-inheritance: - diff --git a/doc/source/api/diffpy.srfit.util.rst b/doc/source/api/diffpy.srfit.util.rst index b96e6945..2471e5ad 100644 --- a/doc/source/api/diffpy.srfit.util.rst +++ b/doc/source/api/diffpy.srfit.util.rst @@ -58,4 +58,3 @@ diffpy.srfit.util.weakrefcallable module :members: :undoc-members: :show-inheritance: - diff --git a/src/diffpy/__init__.py b/src/diffpy/__init__.py index 08edc76b..903acd5f 100644 --- a/src/diffpy/__init__.py +++ b/src/diffpy/__init__.py @@ -21,4 +21,3 @@ __path__ = extend_path(__path__, __name__) # End of file - diff --git a/src/diffpy/srfit/equation/__init__.py b/src/diffpy/srfit/equation/__init__.py index 135a6af2..6a248b32 100644 --- a/src/diffpy/srfit/equation/__init__.py +++ b/src/diffpy/srfit/equation/__init__.py @@ -29,5 +29,4 @@ from diffpy.srfit.equation.equationmod import Equation - # End of file diff --git a/src/diffpy/srfit/equation/builder.py b/src/diffpy/srfit/equation/builder.py index e35e9e11..1b1f6601 100644 --- a/src/diffpy/srfit/equation/builder.py +++ b/src/diffpy/srfit/equation/builder.py @@ -77,9 +77,16 @@ > eq = beq.makeEquation() """ -__all__ = ["EquationFactory", "BaseBuilder", "ArgumentBuilder", - "OperatorBuilder", "wrapArgument", "wrapOperator", "wrapFunction", - "getBuilder"] +__all__ = [ + "EquationFactory", + "BaseBuilder", + "ArgumentBuilder", + "OperatorBuilder", + "wrapArgument", + "wrapOperator", + "wrapFunction", + "getBuilder", +] # NOTE - the builder cannot handle numpy arrays on the left of a binary # operation because the array will automatically loop the operator of the @@ -91,13 +98,13 @@ import inspect import numbers -import numpy +import numpy import six import diffpy.srfit.equation.literals as literals -from diffpy.srfit.equation.literals.literal import Literal from diffpy.srfit.equation.equationmod import Equation +from diffpy.srfit.equation.literals.literal import Literal class EquationFactory(object): @@ -125,8 +132,7 @@ def __init__(self): self.registerConstant("e", numpy.e) return - def makeEquation(self, eqstr, buildargs = True, argclass = - literals.Argument, argkw = {}): + def makeEquation(self, eqstr, buildargs=True, argclass=literals.Argument, argkw={}): """Make an equation from an equation string. Arguments @@ -152,7 +158,7 @@ def makeEquation(self, eqstr, buildargs = True, argclass = # handle scalar numbers or numpy arrays if isinstance(beq, (numbers.Number, numpy.ndarray)): lit = literals.Argument(value=beq, const=True) - eq = Equation(name='', root=lit) + eq = Equation(name="", root=lit) else: eq = beq.getEquation() self.equations.add(eq) @@ -255,7 +261,6 @@ def deRegisterBuilder(self, name): del self.builders[name] return - def wipeout(self, eq): """Invalidate the specified equation and remove it from the factory. @@ -272,11 +277,10 @@ def wipeout(self, eq): self.equations.discard(eq) # invalidate this equation to clean up any observer relations of # objects in the factory towards its literals tree. - nan = literals.Argument('nan', value=numpy.nan, const=True) + nan = literals.Argument("nan", value=numpy.nan, const=True) eq.setRoot(nan) return - def _prepareBuilders(self, eqstr, buildargs, argclass, argkw): """Prepare builders so that equation string can be evaluated. @@ -309,14 +313,14 @@ def _prepareBuilders(self, eqstr, buildargs, argclass, argkw): # this is disallowed. if not buildargs and eqargs: eqargsstr = ", ".join(eqargs) - msg = "The equation contains undefined arguments: %s"%eqargsstr + msg = "The equation contains undefined arguments: %s" % eqargsstr raise ValueError(msg) # Make the arguments newargs = set() for argname in eqargs: - arg = argclass(name = argname, **argkw) - argbuilder = ArgumentBuilder(name = argname, arg = arg) + arg = argclass(name=argname, **argkw) + argbuilder = ArgumentBuilder(name=argname, arg=arg) newargs.add(arg) self.registerBuilder(argname, argbuilder) @@ -333,8 +337,8 @@ def _getUndefinedArgs(self, eqstr): Raises SyntaxError if the equation string uses invalid syntax. """ - import tokenize import token + import tokenize interface = six.StringIO(eqstr).readline # output is an iterator. Each entry (token) is a 5-tuple @@ -353,7 +357,7 @@ def _getUndefinedArgs(self, eqstr): if tok[0] in (token.NAME, token.OP): args.add(tok[1]) except tokenize.TokenError: - m = "invalid syntax: '%s'"%eqstr + m = "invalid syntax: '%s'" % eqstr raise SyntaxError(m) # Scan the tokens for names that do not correspond to registered @@ -363,18 +367,22 @@ def _getUndefinedArgs(self, eqstr): # Move genuine varibles to the eqargs dictionary if ( # Check registered builders - tok in self.builders or + tok in self.builders + or # Check symbols - tok in EquationFactory.symbols or + tok in EquationFactory.symbols + or # Check ignored characters tok in EquationFactory.ignore - ): + ): args.remove(tok) return args + # End class EquationFactory + class BaseBuilder(object): """Class for building equations. @@ -392,11 +400,9 @@ def __init__(self): def __call__(self, *args): """Raises exception for easier debugging.""" - m = "%s (%s) cannot accept arguments"%\ - (self.literal.name, self.__class__.__name__) + m = "%s (%s) cannot accept arguments" % (self.literal.name, self.__class__.__name__) raise TypeError(m) - def getEquation(self): """Get the equation built by this object. @@ -404,11 +410,11 @@ def getEquation(self): name of the root node. """ # We need to make a name for this, so we name it after its root - name = "_eq_%s"%self.literal.name + name = "_eq_%s" % self.literal.name eq = Equation(name, self.literal) return eq - def __evalBinary(self, other, OperatorClass, onleft = True): + def __evalBinary(self, other, OperatorClass, onleft=True): """Evaluate a binary function. Other can be an BaseBuilder or a constant. @@ -498,8 +504,10 @@ def __rmod__(self, other): def __neg__(self): return self.__evalUnary(literals.NegationOperator) + ## These are used by the class. + class ArgumentBuilder(BaseBuilder): """BaseBuilder wrapper around an Argument literal. @@ -510,7 +518,7 @@ class ArgumentBuilder(BaseBuilder): literal -- The Argument wrapped by this instance. """ - def __init__(self, value = None, name = None, const = False, arg = None): + def __init__(self, value=None, name=None, const=False, arg=None): """Create an ArgumentBuilder instance, containing a new Argument. Arguments @@ -524,14 +532,15 @@ def __init__(self, value = None, name = None, const = False, arg = None): """ BaseBuilder.__init__(self) if arg is None: - self.literal = literals.Argument(value=value, name=name, - const=const) + self.literal = literals.Argument(value=value, name=name, const=const) else: self.literal = arg return + # end class ArgumentBuilder + class OperatorBuilder(BaseBuilder): """BaseBuilder wrapper around an Operator literal. @@ -540,7 +549,7 @@ class OperatorBuilder(BaseBuilder): name -- The name of the operator to be wrapped """ - def __init__(self, name, op = None): + def __init__(self, name, op=None): """Wrap an Operator or a function by name. Arguments @@ -573,43 +582,48 @@ def __call__(self, *args): self.literal = literals.UFuncOperator(ufunc) # Here the Operator is already specified. We can copy its attributes # to a new Operator inside of the new OperatorBuilder. - op = literals.makeOperator(name=self.literal.name, - symbol=self.literal.symbol, - nin=self.literal.nin, - nout=self.literal.nout, - operation=self.literal.operation) + op = literals.makeOperator( + name=self.literal.name, + symbol=self.literal.symbol, + nin=self.literal.nin, + nout=self.literal.nout, + operation=self.literal.operation, + ) newobj.literal = op # Now that we have a literal, let's check our inputs literal = newobj.literal if literal.nin >= 0 and len(args) != literal.nin: - raise ValueError("%s takes %i arguments (%i given)"%\ - (self.literal, self.literal.nin, len(args))) + raise ValueError("%s takes %i arguments (%i given)" % (self.literal, self.literal.nin, len(args))) # Wrap scalar arguments for i, arg in enumerate(args): # Wrap the argument if it is not already if not isinstance(arg, BaseBuilder): - name = self.name + "_%i"%i - arg = ArgumentBuilder(value = arg, name = name, const = True) + name = self.name + "_%i" % i + arg = ArgumentBuilder(value=arg, name=name, const=True) newobj.literal.addLiteral(arg.literal) return newobj + # end class OperatorBuilder # Utility functions + def wrapArgument(name, arg): """Wrap an Argument as a builder.""" - argbuilder = ArgumentBuilder(arg = arg) + argbuilder = ArgumentBuilder(arg=arg) return argbuilder + def wrapOperator(name, op): """Wrap an Operator as a builder.""" opbuilder = OperatorBuilder(name, op) return opbuilder + def wrapFunction(name, func, nin=2, nout=1): """Wrap a function in an OperatorBuilder instance. @@ -620,19 +634,19 @@ def wrapFunction(name, func, nin=2, nout=1): Returns the OperatorBuilder instance that wraps the function. """ - op = literals.makeOperator(name=name, symbol=name, - nin=nin, nout=nout, - operation=func) + op = literals.makeOperator(name=name, symbol=name, nin=nin, nout=nout, operation=func) # Create the OperatorBuilder opbuilder = OperatorBuilder(name, op) return opbuilder + def getBuilder(name): """Get an operator from the global builders dictionary.""" return _builders[name] + def __wrapNumpyOperators(): """Export all numpy operators as OperatorBuilder instances in the module namespace. @@ -642,8 +656,11 @@ def __wrapNumpyOperators(): if isinstance(op, numpy.ufunc): _builders[name] = OperatorBuilder(name) return + + __wrapNumpyOperators() + # Register other functions as well def __wrapSrFitOperators(): """Export all non-base operators from the @@ -653,16 +670,20 @@ def __wrapSrFitOperators(): opmod = literals.operators excluded_types = set((opmod.CustomOperator, opmod.UFuncOperator)) # check if opmod member should be wrapped as OperatorBuilder - is_exported_type = lambda cls : ( - inspect.isclass(cls) and issubclass(cls, opmod.Operator) and - not inspect.isabstract(cls) and - not cls in excluded_types) + is_exported_type = lambda cls: ( + inspect.isclass(cls) + and issubclass(cls, opmod.Operator) + and not inspect.isabstract(cls) + and not cls in excluded_types + ) # create OperatorBuilder objects for nm, opclass in inspect.getmembers(opmod, is_exported_type): op = opclass() assert op.name, "Unnamed Operator should never appear here." _builders[op.name] = OperatorBuilder(op.name, op) return + + __wrapSrFitOperators() # End of file diff --git a/src/diffpy/srfit/equation/equationmod.py b/src/diffpy/srfit/equation/equationmod.py index a48d6dad..60dd2c62 100644 --- a/src/diffpy/srfit/equation/equationmod.py +++ b/src/diffpy/srfit/equation/equationmod.py @@ -42,9 +42,10 @@ from collections import OrderedDict -from diffpy.srfit.equation.visitors import validate, getArgs, swap -from diffpy.srfit.equation.literals.operators import Operator from diffpy.srfit.equation.literals.literal import Literal +from diffpy.srfit.equation.literals.operators import Operator +from diffpy.srfit.equation.visitors import getArgs, swap, validate + class Equation(Operator): """Class for holding and evaluating a Literal tree. @@ -81,7 +82,7 @@ class Equation(Operator): nin = None nout = 1 - def __init__(self, name = None, root = None): + def __init__(self, name=None, root=None): """Initialize. name -- A name for this Equation. @@ -93,7 +94,7 @@ def __init__(self, name = None, root = None): # Operator stuff. We circumvent Operator.__init__ since we're using # args as a property. We cannot set it, as the Operator tries to do. if name is None and root is not None: - name = "eq_%s"%root.name + name = "eq_%s" % root.name Literal.__init__(self, name) self.root = None self.argdict = OrderedDict() @@ -101,12 +102,10 @@ def __init__(self, name = None, root = None): self.setRoot(root) return - @property def symbol(self): return self.name - def operation(self, *args, **kw): """Evaluate this Equation object. @@ -117,7 +116,6 @@ def operation(self, *args, **kw): """ return self.__call__(*args, **kw) - def _getArgs(self): return list(self.argdict.values()) @@ -126,16 +124,13 @@ def _getArgs(self): def __getattr__(self, name): """Gives access to the Arguments as attributes.""" # Avoid infinite loop on argdict lookup. - argdict = object.__getattribute__(self, 'argdict') + argdict = object.__getattribute__(self, "argdict") if not name in argdict: raise AttributeError("No argument named '%s' here" % name) return argdict[name] - # Ensure there is no __dir__ override in the base class. - assert (getattr(Operator, '__dir__', None) is - getattr(object, '__dir__', None)) - + assert getattr(Operator, "__dir__", None) is getattr(object, "__dir__", None) def __dir__(self): "Return sorted list of attributes for this object." @@ -144,7 +139,6 @@ def __dir__(self): rv = sorted(rv) return rv - def setRoot(self, root): """Set the root of the Literal tree. @@ -167,14 +161,13 @@ def setRoot(self, root): # Get the args args = getArgs(root, getconsts=False) - self.argdict = OrderedDict( [(arg.name, arg) for arg in args] ) + self.argdict = OrderedDict([(arg.name, arg) for arg in args]) # Set Operator attributes self.nin = len(self.args) return - def __call__(self, *args, **kw): """Call the equation. @@ -196,7 +189,7 @@ def __call__(self, *args, **kw): for name, val in kw.items(): arg = self.argdict.get(name) if arg is None: - raise ValueError("No argument named '%s' here"%name) + raise ValueError("No argument named '%s' here" % name) arg.setValue(val) self._value = self.root.getValue() @@ -224,4 +217,5 @@ def identify(self, visitor): """Identify self to a visitor.""" return visitor.onEquation(self) + # End of file diff --git a/src/diffpy/srfit/equation/literals/__init__.py b/src/diffpy/srfit/equation/literals/__init__.py index 34c38cef..1632316c 100644 --- a/src/diffpy/srfit/equation/literals/__init__.py +++ b/src/diffpy/srfit/equation/literals/__init__.py @@ -25,32 +25,47 @@ (http://en.wikipedia.org/wiki/Visitor_pattern). """ -__all__ = ["Argument", "Operator", "BinaryOperator", "CustomOperator", - "AdditionOperator", "SubtractionOperator", - "MultiplicationOperator", "DivisionOperator", "ExponentiationOperator", - "RemainderOperator", "NegationOperator", "ConvolutionOperator", - "SumOperator", "UFuncOperator", "ArrayOperator", "PolyvalOperator", - "makeOperator"] +__all__ = [ + "Argument", + "Operator", + "BinaryOperator", + "CustomOperator", + "AdditionOperator", + "SubtractionOperator", + "MultiplicationOperator", + "DivisionOperator", + "ExponentiationOperator", + "RemainderOperator", + "NegationOperator", + "ConvolutionOperator", + "SumOperator", + "UFuncOperator", + "ArrayOperator", + "PolyvalOperator", + "makeOperator", +] # Import the operators from diffpy.srfit.equation.literals.argument import Argument -from diffpy.srfit.equation.literals.operators import Operator -from diffpy.srfit.equation.literals.operators import BinaryOperator -from diffpy.srfit.equation.literals.operators import CustomOperator -from diffpy.srfit.equation.literals.operators import AdditionOperator -from diffpy.srfit.equation.literals.operators import SubtractionOperator -from diffpy.srfit.equation.literals.operators import MultiplicationOperator -from diffpy.srfit.equation.literals.operators import DivisionOperator -from diffpy.srfit.equation.literals.operators import ExponentiationOperator -from diffpy.srfit.equation.literals.operators import RemainderOperator -from diffpy.srfit.equation.literals.operators import NegationOperator -from diffpy.srfit.equation.literals.operators import ConvolutionOperator -from diffpy.srfit.equation.literals.operators import UFuncOperator -from diffpy.srfit.equation.literals.operators import SumOperator -from diffpy.srfit.equation.literals.operators import ArrayOperator -from diffpy.srfit.equation.literals.operators import PolyvalOperator -from diffpy.srfit.equation.literals.operators import makeOperator +from diffpy.srfit.equation.literals.operators import ( + AdditionOperator, + ArrayOperator, + BinaryOperator, + ConvolutionOperator, + CustomOperator, + DivisionOperator, + ExponentiationOperator, + MultiplicationOperator, + NegationOperator, + Operator, + PolyvalOperator, + RemainderOperator, + SubtractionOperator, + SumOperator, + UFuncOperator, + makeOperator, +) # End of file diff --git a/src/diffpy/srfit/equation/literals/abcs.py b/src/diffpy/srfit/equation/literals/abcs.py index 05099162..2186b9bb 100644 --- a/src/diffpy/srfit/equation/literals/abcs.py +++ b/src/diffpy/srfit/equation/literals/abcs.py @@ -28,13 +28,16 @@ class LiteralABC(object): """Abstract Base Class for Literal. See Literal for usage.""" @abstractmethod - def identify(self, visitor): pass + def identify(self, visitor): + pass @abstractmethod - def getValue(self): pass + def getValue(self): + pass name = abstractproperty(None, None) + # End class LiteralABC @@ -42,11 +45,13 @@ class ArgumentABC(LiteralABC): """Abstract Base Class for Argument. See Argument for usage.""" @abstractmethod - def setValue(self, value): pass + def setValue(self, value): + pass const = abstractproperty(None, None) value = abstractproperty(None, None) + # End class ArgumentABC @@ -54,7 +59,8 @@ class OperatorABC(LiteralABC): """Abstract Base Class for Operator. See Operator for usage.""" @abstractmethod - def addLiteral(self, literal): pass + def addLiteral(self, literal): + pass args = abstractproperty(None, None) nin = abstractproperty(None, None) @@ -63,4 +69,5 @@ def addLiteral(self, literal): pass symbol = abstractproperty(None, None) value = abstractproperty(None, None) + # End class OperatorABC diff --git a/src/diffpy/srfit/equation/literals/argument.py b/src/diffpy/srfit/equation/literals/argument.py index ccd9a124..0843e7c5 100644 --- a/src/diffpy/srfit/equation/literals/argument.py +++ b/src/diffpy/srfit/equation/literals/argument.py @@ -21,10 +21,12 @@ __all__ = ["Argument"] -from numpy import ndarray, array_equal +from numpy import array_equal, ndarray + from diffpy.srfit.equation.literals.abcs import ArgumentABC from diffpy.srfit.equation.literals.literal import Literal + class Argument(Literal, ArgumentABC): """Argument class. @@ -39,7 +41,7 @@ class Argument(Literal, ArgumentABC): const = None - def __init__(self, name = None, value = None, const = False): + def __init__(self, name=None, value=None, const=False): """Initialization.""" Literal.__init__(self, name) self.const = const @@ -69,7 +71,7 @@ def setValue(self, val): self.notify() return - value = property( lambda self: self.getValue(), - lambda self, val: self.setValue(val)) + value = property(lambda self: self.getValue(), lambda self, val: self.setValue(val)) + # End of file diff --git a/src/diffpy/srfit/equation/literals/literal.py b/src/diffpy/srfit/equation/literals/literal.py index f1f460f4..26523ac0 100644 --- a/src/diffpy/srfit/equation/literals/literal.py +++ b/src/diffpy/srfit/equation/literals/literal.py @@ -25,7 +25,8 @@ from diffpy.srfit.equation.literals.abcs import LiteralABC from diffpy.srfit.util.observable import Observable -class Literal(Observable,LiteralABC): + +class Literal(Observable, LiteralABC): """Abstract class for equation pieces, such as operators and arguments. Literal derives from Observable. See diffpy.srfit.util.observable. @@ -64,6 +65,7 @@ def _flush(self, other): return def __str__(self): - return "%s(%s)"%(self.__class__.__name__, self.name) + return "%s(%s)" % (self.__class__.__name__, self.name) + # End of file diff --git a/src/diffpy/srfit/equation/literals/operators.py b/src/diffpy/srfit/equation/literals/operators.py index 0a3f679e..3c279397 100644 --- a/src/diffpy/srfit/equation/literals/operators.py +++ b/src/diffpy/srfit/equation/literals/operators.py @@ -25,10 +25,21 @@ but they all identify themselves with the Visitor.onOperator method. """ -__all__ = ["Operator", "AdditionOperator", "SubtractionOperator", - "MultiplicationOperator", "DivisionOperator", "ExponentiationOperator", - "RemainderOperator", "NegationOperator", "ConvolutionOperator", - "SumOperator", "UFuncOperator", "ArrayOperator", "PolyvalOperator"] +__all__ = [ + "Operator", + "AdditionOperator", + "SubtractionOperator", + "MultiplicationOperator", + "DivisionOperator", + "ExponentiationOperator", + "RemainderOperator", + "NegationOperator", + "ConvolutionOperator", + "SumOperator", + "UFuncOperator", + "ArrayOperator", + "PolyvalOperator", +] import numpy @@ -71,13 +82,11 @@ class Operator(Literal, OperatorABC): # _value : float, numpy.ndarray or None # The last value of the operator or None. - # We must declare the abstract `args` here. args = None # default for the value _value = None - def __init__(self, name=None): """Initialize the operator object with the specified name. @@ -91,7 +100,6 @@ def __init__(self, name=None): self.args = [] return - def identify(self, visitor): """Identify self to a visitor.""" return visitor.onOperator(self) @@ -124,7 +132,7 @@ def getValue(self): def _loopCheck(self, literal): """Check if a literal causes self-reference.""" if literal is self: - raise ValueError("'%s' causes self-reference"%literal) + raise ValueError("'%s' causes self-reference" % literal) # Check to see if I am a dependency of the literal. if hasattr(literal, "args"): @@ -206,6 +214,7 @@ def makeOperator(name, symbol, operation, nin, nout): op.nout = nout return op + # Some specified operators @@ -278,10 +287,10 @@ def _conv(v1, v2): # Find the centroid of the first signal s1 = sum(v1) x1 = numpy.arange(len(v1), dtype=float) - c1idx = numpy.sum(v1 * x1)/s1 + c1idx = numpy.sum(v1 * x1) / s1 # Find the centroid of the convolution xc = numpy.arange(len(c), dtype=float) - ccidx = numpy.sum(c * xc)/sum(c) + ccidx = numpy.sum(c * xc) / sum(c) # Interpolate the convolution such that the centroids line up. This # uses linear interpolation. shift = ccidx - c1idx @@ -291,7 +300,7 @@ def _conv(v1, v2): # Normalize sc = sum(c) if sc > 0: - c *= s1/sc + c *= s1 / sc return c @@ -370,4 +379,5 @@ class PolyvalOperator(BinaryOperator): operation = staticmethod(numpy.polyval) pass + # End of file diff --git a/src/diffpy/srfit/equation/visitors/__init__.py b/src/diffpy/srfit/equation/visitors/__init__.py index b4014c3e..c329a324 100644 --- a/src/diffpy/srfit/equation/visitors/__init__.py +++ b/src/diffpy/srfit/equation/visitors/__init__.py @@ -27,11 +27,11 @@ from diffpy.srfit.equation.visitors.argfinder import ArgFinder from diffpy.srfit.equation.visitors.printer import Printer -from diffpy.srfit.equation.visitors.validator import Validator from diffpy.srfit.equation.visitors.swapper import Swapper +from diffpy.srfit.equation.visitors.validator import Validator -def getArgs(literal, getconsts = True): +def getArgs(literal, getconsts=True): """Get the Arguments of a Literal tree. getconsts -- If True (default), then Arguments designated as constant @@ -72,7 +72,7 @@ def validate(literal): v = Validator() errors = literal.identify(v) if errors: - m = "Errors found in Literal tree '%s'\n"%literal + m = "Errors found in Literal tree '%s'\n" % literal m += "\n".join(errors) raise ValueError(m) return diff --git a/src/diffpy/srfit/equation/visitors/argfinder.py b/src/diffpy/srfit/equation/visitors/argfinder.py index ab26a695..3a45460c 100644 --- a/src/diffpy/srfit/equation/visitors/argfinder.py +++ b/src/diffpy/srfit/equation/visitors/argfinder.py @@ -32,7 +32,7 @@ class ArgFinder(Visitor): """ - def __init__(self, getconsts = True): + def __init__(self, getconsts=True): """Initialize. Arguments @@ -61,4 +61,5 @@ def onOperator(self, op): arg.identify(self) return self.args + # End of file diff --git a/src/diffpy/srfit/equation/visitors/printer.py b/src/diffpy/srfit/equation/visitors/printer.py index 9b98414c..c48e8c9c 100644 --- a/src/diffpy/srfit/equation/visitors/printer.py +++ b/src/diffpy/srfit/equation/visitors/printer.py @@ -25,6 +25,7 @@ from diffpy.srfit.equation.visitors.visitor import Visitor + class Printer(Visitor): """Printer for printing a Literal tree. @@ -44,13 +45,11 @@ def __init__(self): self.reset() return - def reset(self): """Reset the out put string.""" self.output = "" return - @property def eqskip(self): """Pattern for equation objects to be skipped. @@ -70,7 +69,6 @@ def eqskip(self, value): self._eqpat = re.compile(value) return - def onArgument(self, arg): """Process an Argument node. @@ -82,7 +80,6 @@ def onArgument(self, arg): self.output += str(arg.name) return self.output - def onOperator(self, op): """Process an Operator node.""" # We have to deal with infix operators @@ -93,31 +90,30 @@ def onOperator(self, op): self.output += str(op.name) + "(" for idx, literal in enumerate(op.args): - if idx != 0: self.output += ", " + if idx != 0: + self.output += ", " literal.identify(self) self.output += ")" return self.output - def onEquation(self, eq): """Process an Equation node.""" - skipthis = (self._eqpat is not None and eq.name and - self._eqpat.match(eq.name)) + skipthis = self._eqpat is not None and eq.name and self._eqpat.match(eq.name) if skipthis: self.onArgument(eq) else: eq.root.identify(self) return self.output - def _onInfix(self, op): """Process infix operators.""" self.output += "(" op.args[0].identify(self) - self.output += " %s "%op.symbol + self.output += " %s " % op.symbol op.args[1].identify(self) self.output += ")" return + # End of file diff --git a/src/diffpy/srfit/equation/visitors/swapper.py b/src/diffpy/srfit/equation/visitors/swapper.py index 0b52a558..1ac9e8c9 100644 --- a/src/diffpy/srfit/equation/visitors/swapper.py +++ b/src/diffpy/srfit/equation/visitors/swapper.py @@ -20,6 +20,7 @@ from diffpy.srfit.equation.visitors.visitor import Visitor + class Swapper(Visitor): """Swapper for swapping out one literal for another in a literal tree. @@ -113,7 +114,6 @@ def onOperator(self, op): newlit.addObserver(op._flush) op._flush(other=()) - self._swap = False return @@ -143,4 +143,5 @@ def onEquation(self, eq): return + # End of file diff --git a/src/diffpy/srfit/equation/visitors/validator.py b/src/diffpy/srfit/equation/visitors/validator.py index c99b6abe..1ccbdbab 100644 --- a/src/diffpy/srfit/equation/visitors/validator.py +++ b/src/diffpy/srfit/equation/visitors/validator.py @@ -61,7 +61,7 @@ def onArgument(self, arg): """ if not isinstance(arg, ArgumentABC): - m = msg%(arg, ArgumentABC.__name__) + m = msg % (arg, ArgumentABC.__name__) self.errors.append(m) self._nin = 1 return self.errors @@ -75,24 +75,24 @@ def onOperator(self, op): """ if not isinstance(op, OperatorABC): - m = msg%(op, OperatorABC.__name__) + m = msg % (op, OperatorABC.__name__) self.errors.append(m) # Can only process single-valued functions if op.nout != 1: - m = "'%s' is not single-valued (nout != 1)"%op + m = "'%s' is not single-valued (nout != 1)" % op self.errors.append(m) # Check name if op.name is None: - m = "'%s' does not have a name"%op + m = "'%s' does not have a name" % op self.errors.append(m) # Check symbol if op.symbol is None: - m = "'%s' does not have a symbol"%op + m = "'%s' does not have a symbol" % op self.errors.append(m) # Check operation without evaluating it if op.operation is None: - m = "'%s' does not define and operation"%op + m = "'%s' does not define and operation" % op self.errors.append(m) localnin = 0 @@ -103,10 +103,11 @@ def onOperator(self, op): # Check the input/output balance if op.nin >= 0 and localnin != op.nin: - m = "'%s' requires %i inputs but receives %i"%(op, op.nin, localnin) + m = "'%s' requires %i inputs but receives %i" % (op, op.nin, localnin) self.errors.append(m) self._nin = op.nout return self.errors + # End of file diff --git a/src/diffpy/srfit/equation/visitors/visitor.py b/src/diffpy/srfit/equation/visitors/visitor.py index ef4eaa65..75f0efa9 100644 --- a/src/diffpy/srfit/equation/visitors/visitor.py +++ b/src/diffpy/srfit/equation/visitors/visitor.py @@ -29,6 +29,7 @@ __all__ = ["Visitor"] + class Visitor(object): """Abstract class for all visitors to a Literal tree. @@ -55,8 +56,7 @@ def onEquation(self, eq): # throw an exception def _abstract(self, method): - raise NotImplementedError( - "class '%s' should override method '%s'" % (self.__class__.__name__, method)) + raise NotImplementedError("class '%s' should override method '%s'" % (self.__class__.__name__, method)) # End of file diff --git a/src/diffpy/srfit/exceptions.py b/src/diffpy/srfit/exceptions.py index eed5a572..7d93fbb2 100644 --- a/src/diffpy/srfit/exceptions.py +++ b/src/diffpy/srfit/exceptions.py @@ -20,9 +20,11 @@ class SrFitError(Exception): """Generic error in SrFit expressions or recipe.""" + pass class ParseError(Exception): """Exception used by ProfileParsers.""" + pass diff --git a/src/diffpy/srfit/fitbase/__init__.py b/src/diffpy/srfit/fitbase/__init__.py index 48b96c79..f07cfd6c 100644 --- a/src/diffpy/srfit/fitbase/__init__.py +++ b/src/diffpy/srfit/fitbase/__init__.py @@ -28,17 +28,26 @@ http://www.reflectometry.org/danse/park.html """ -__all__ = ['Calculator', 'FitContribution', 'FitHook', 'FitRecipe', - 'FitResults', 'initializeRecipe', 'PlotFitHook', 'Profile', - 'ProfileGenerator', 'SimpleRecipe'] +__all__ = [ + "Calculator", + "FitContribution", + "FitHook", + "FitRecipe", + "FitResults", + "initializeRecipe", + "PlotFitHook", + "Profile", + "ProfileGenerator", + "SimpleRecipe", +] from diffpy.srfit.fitbase.calculator import Calculator from diffpy.srfit.fitbase.fitcontribution import FitContribution from diffpy.srfit.fitbase.fithook import FitHook, PlotFitHook from diffpy.srfit.fitbase.fitrecipe import FitRecipe -from diffpy.srfit.fitbase.simplerecipe import SimpleRecipe from diffpy.srfit.fitbase.fitresults import FitResults, initializeRecipe from diffpy.srfit.fitbase.profile import Profile from diffpy.srfit.fitbase.profilegenerator import ProfileGenerator +from diffpy.srfit.fitbase.simplerecipe import SimpleRecipe # End of file diff --git a/src/diffpy/srfit/fitbase/calculator.py b/src/diffpy/srfit/fitbase/calculator.py index 43f91ec1..ee36f4af 100644 --- a/src/diffpy/srfit/fitbase/calculator.py +++ b/src/diffpy/srfit/fitbase/calculator.py @@ -26,8 +26,9 @@ __all__ = ["Calculator"] -from diffpy.srfit.fitbase.parameterset import ParameterSet from diffpy.srfit.equation.literals.operators import Operator +from diffpy.srfit.fitbase.parameterset import ParameterSet + class Calculator(Operator, ParameterSet): """Base class for calculators. @@ -75,12 +76,10 @@ def __init__(self, name): Operator.__init__(self, name) return - @property def symbol(self): return self.name - # Overload me! def __call__(self, *args): """Calculate something. @@ -92,12 +91,10 @@ def __call__(self, *args): """ return 0 - def operation(self, *args): self._value = self.__call__(*args) return self._value - def _validate(self): """Validate my state. @@ -112,4 +109,5 @@ def _validate(self): return + # End class Calculator diff --git a/src/diffpy/srfit/fitbase/configurable.py b/src/diffpy/srfit/fitbase/configurable.py index 652cad0d..dab99dda 100644 --- a/src/diffpy/srfit/fitbase/configurable.py +++ b/src/diffpy/srfit/fitbase/configurable.py @@ -54,6 +54,7 @@ def _storeConfigurable(self, obj): self._configobjs.add(obj) return + # End class Configurable # End of file diff --git a/src/diffpy/srfit/fitbase/constraint.py b/src/diffpy/srfit/fitbase/constraint.py index 82c54897..2c0ca8f9 100644 --- a/src/diffpy/srfit/fitbase/constraint.py +++ b/src/diffpy/srfit/fitbase/constraint.py @@ -41,7 +41,7 @@ class Constraint(Validatable): """ def __init__(self): - """Initialization. """ + """Initialization.""" self.par = None self.eq = None return @@ -57,10 +57,10 @@ def constrain(self, par, eq): """ if par.const: - raise ValueError("The parameter '%s' is constant"%par) + raise ValueError("The parameter '%s' is constant" % par) if par.constrained: - raise ValueError("The parameter '%s' is already constrained"%par) + raise ValueError("The parameter '%s' is already constrained" % par) par.constrained = True @@ -100,6 +100,7 @@ def _validate(self): raise SrFitError("eq is None") self.par._validate() from diffpy.srfit.equation.visitors import validate + try: validate(self.eq) except ValueError as e: @@ -117,4 +118,5 @@ def _validate(self): return + # End of file diff --git a/src/diffpy/srfit/fitbase/fitcontribution.py b/src/diffpy/srfit/fitbase/fitcontribution.py index 1e80ce0e..d2982fd9 100644 --- a/src/diffpy/srfit/fitbase/fitcontribution.py +++ b/src/diffpy/srfit/fitbase/fitcontribution.py @@ -25,11 +25,12 @@ __all__ = ["FitContribution"] -from diffpy.srfit.fitbase.parameterset import ParameterSet -from diffpy.srfit.fitbase.recipeorganizer import equationFromString +from diffpy.srfit.exceptions import SrFitError from diffpy.srfit.fitbase.parameter import ParameterProxy +from diffpy.srfit.fitbase.parameterset import ParameterSet from diffpy.srfit.fitbase.profile import Profile -from diffpy.srfit.exceptions import SrFitError +from diffpy.srfit.fitbase.recipeorganizer import equationFromString + class FitContribution(ParameterSet): """FitContribution class. @@ -80,7 +81,7 @@ def __init__(self, name): self._manage(self._generators) return - def setProfile(self, profile, xname = None, yname = None, dyname = None): + def setProfile(self, profile, xname=None, yname=None, dyname=None): """Assign the Profile for this FitContribution. profile -- A Profile that specifies the calculation points and that @@ -121,9 +122,9 @@ def setProfile(self, profile, xname = None, yname = None, dyname = None): xpar = ParameterProxy(xname, self.profile.xpar) ypar = ParameterProxy(yname, self.profile.ypar) dypar = ParameterProxy(dyname, self.profile.dypar) - self.addParameter(xpar, check = False) - self.addParameter(ypar, check = False) - self.addParameter(dypar, check = False) + self.addParameter(xpar, check=False) + self.addParameter(ypar, check=False) + self.addParameter(dypar, check=False) # If we have ProfileGenerators, set their Profiles. for gen in self._generators.values(): @@ -131,12 +132,11 @@ def setProfile(self, profile, xname = None, yname = None, dyname = None): # If we have _eq, but not _reseq, set the residual if self._eq is not None and self._reseq is None: - self.setResidualEquation('chiv') + self.setResidualEquation("chiv") return - - def addProfileGenerator(self, gen, name = None): + def addProfileGenerator(self, gen, name=None): """Add a ProfileGenerator to be used by this FitContribution. The ProfileGenerator is given a name so that it can be used as part of @@ -176,7 +176,7 @@ def addProfileGenerator(self, gen, name = None): return - def setEquation(self, eqstr, ns = {}): + def setEquation(self, eqstr, ns={}): """Set the profile equation for the FitContribution. This sets the equation that will be used when generating the residual @@ -197,8 +197,7 @@ def setEquation(self, eqstr, ns = {}): """ # Build the equation instance. - eq = equationFromString(eqstr, self._eqfactory, - buildargs=True, ns=ns) + eq = equationFromString(eqstr, self._eqfactory, buildargs=True, ns=ns) eq.name = "eq" # Register any new Parameters. @@ -212,11 +211,10 @@ def setEquation(self, eqstr, ns = {}): # Set the residual if we need to if self.profile is not None and self._reseq is None: - self.setResidualEquation('chiv') + self.setResidualEquation("chiv") return - def getEquation(self): """Get math expression string for the active profile equation. @@ -224,12 +222,12 @@ def getEquation(self): equation has not been set yet. """ from diffpy.srfit.equation.visitors import getExpression + rv = "" if self._eq is not None: rv = getExpression(self._eq) return rv - def setResidualEquation(self, eqstr): """Set the residual equation for the FitContribution. @@ -271,7 +269,6 @@ def setResidualEquation(self, eqstr): return - def getResidualEquation(self): """Get math expression string for the active residual equation. @@ -279,12 +276,12 @@ def getResidualEquation(self): equation has not been configured yet. """ from diffpy.srfit.equation.visitors import getExpression + rv = "" if self._reseq is not None: - rv = getExpression(self._reseq, eqskip='eq$') + rv = getExpression(self._reseq, eqskip="eq$") return rv - def residual(self): """Calculate the residual for this fitcontribution. @@ -306,16 +303,13 @@ def residual(self): # the following will not recompute the equation. return self._reseq() - def evaluate(self): - """Evaluate the contribution equation and update profile.ycalc. - """ + """Evaluate the contribution equation and update profile.ycalc.""" yc = self._eq() if self.profile is not None: self.profile.ycalc = yc return yc - def _validate(self): """Validate my state. @@ -332,6 +326,7 @@ def _validate(self): # Try to get the value of eq. from diffpy.srfit.equation.visitors import validate + try: validate(self._eq) except ValueError as e: @@ -343,7 +338,7 @@ def _validate(self): try: val = self._eq() except TypeError as e: - raise SrFitError("_eq cannot be evaluated: %s"%e) + raise SrFitError("_eq cannot be evaluated: %s" % e) if val is None: raise SrFitError("_eq evaluates to None") @@ -361,4 +356,5 @@ def _validate(self): raise SrFitError("residual evaluates to None") return + # End of file diff --git a/src/diffpy/srfit/fitbase/fithook.py b/src/diffpy/srfit/fitbase/fithook.py index 7dc2de96..98d8757a 100644 --- a/src/diffpy/srfit/fitbase/fithook.py +++ b/src/diffpy/srfit/fitbase/fithook.py @@ -71,8 +71,10 @@ def postcall(self, recipe, chiv): """ return + # End class FitHook + class PrintFitHook(FitHook): """Base class for inspecting the progress of a FitRecipe refinement. @@ -148,14 +150,16 @@ def postcall(self, recipe, chiv): print("Variables") vnames = recipe.getNames() vals = recipe.getValues() - byname = lambda nv : sortKeyForNumericString(nv[0]) + byname = lambda nv: sortKeyForNumericString(nv[0]) items = sorted(zip(vnames, vals), key=byname) for name, val in items: print(" %s = %f" % (name, val)) return + # End class PrintFitHook + # TODO - Display the chi^2 on the plot during refinement. class PlotFitHook(FitHook): """This FitHook has live plotting of whatever is being refined.""" @@ -185,20 +189,20 @@ def reset(self, recipe): # Create a subplot if nc > 1: - pylab.subplot(nrows, ncols, idx+1) - pdata = pylab.plot(p.x, p.y, 'bo')[0] - pfit = pylab.plot(p.x, p.y, 'r-')[0] + pylab.subplot(nrows, ncols, idx + 1) + pdata = pylab.plot(p.x, p.y, "bo")[0] + pfit = pylab.plot(p.x, p.y, "r-")[0] self._plots.append((pdata, pfit)) pylab.xlabel(xname) pylab.ylabel(yname) pylab.title(name) # Set up some event handling, so things behave nicely. - #def redraw(event): + # def redraw(event): # canvas = event.canvas # canvas.draw() # return - #pylab.connect('resize_event', redraw) + # pylab.connect('resize_event', redraw) return diff --git a/src/diffpy/srfit/fitbase/fitrecipe.py b/src/diffpy/srfit/fitbase/fitrecipe.py index c367f78b..347ce0b9 100644 --- a/src/diffpy/srfit/fitbase/fitrecipe.py +++ b/src/diffpy/srfit/fitbase/fitrecipe.py @@ -35,14 +35,15 @@ __all__ = ["FitRecipe"] from collections import OrderedDict -from numpy import array, concatenate, sqrt, dot + import six +from numpy import array, concatenate, dot, sqrt -from diffpy.srfit.interface import _fitrecipe_interface -from diffpy.srfit.util.tagmanager import TagManager +from diffpy.srfit.fitbase.fithook import PrintFitHook from diffpy.srfit.fitbase.parameter import ParameterProxy from diffpy.srfit.fitbase.recipeorganizer import RecipeOrganizer -from diffpy.srfit.fitbase.fithook import PrintFitHook +from diffpy.srfit.interface import _fitrecipe_interface +from diffpy.srfit.util.tagmanager import TagManager class FitRecipe(_fitrecipe_interface, RecipeOrganizer): @@ -87,18 +88,20 @@ class FitRecipe(_fitrecipe_interface, RecipeOrganizer): bounds2 -- Bounds on parameters (read only). See getBounds2. """ - fixednames = property(lambda self: - [v.name for v in self._parameters.values() - if not (self.isFree(v) or self.isConstrained(v))], - doc='names of the fixed refinable variables') - fixedvalues = property(lambda self: - array([v.value for v in self._parameters.values() - if not (self.isFree(v) or self.isConstrained(v))]), - doc='values of the fixed refinable variables') + fixednames = property( + lambda self: [v.name for v in self._parameters.values() if not (self.isFree(v) or self.isConstrained(v))], + doc="names of the fixed refinable variables", + ) + fixedvalues = property( + lambda self: array( + [v.value for v in self._parameters.values() if not (self.isFree(v) or self.isConstrained(v))] + ), + doc="values of the fixed refinable variables", + ) bounds = property(lambda self: self.getBounds()) bounds2 = property(lambda self: self.getBounds2()) - def __init__(self, name = "fit"): + def __init__(self, name="fit"): """Initialization.""" RecipeOrganizer.__init__(self, name) self.fithooks = [] @@ -119,7 +122,7 @@ def __init__(self, name = "fit"): return - def pushFitHook(self, fithook, index = None): + def pushFitHook(self, fithook, index=None): """Add a FitHook to be called within the residual method. The hook is an object for reporting updates, or more fundamentally, @@ -138,7 +141,7 @@ def pushFitHook(self, fithook, index = None): self._updateConfiguration() return - def popFitHook(self, fithook = None, index = -1): + def popFitHook(self, fithook=None, index=-1): """Remove a FitHook by index or reference. fithook -- FitHook instance to remove from the sequence. If this is @@ -164,7 +167,7 @@ def clearFitHooks(self): del self.fithooks[:] return - def addContribution(self, con, weight = 1.0): + def addContribution(self, con, weight=1.0): """Add a FitContribution to the FitRecipe. con -- The FitContribution to be stored. @@ -203,7 +206,7 @@ def removeParameterSet(self, parset): self._removeObject(parset, self._parsets) return - def residual(self, p = []): + def residual(self, p=[]): """Calculate the vector residual to be optimized. Arguments @@ -234,22 +237,22 @@ def residual(self, p = []): con.update() # Calculate the bare chiv - chiv = concatenate([ - wi * ci.residual().flatten() - for wi, ci in zip(self._weights, self._contributions.values())]) + chiv = concatenate( + [wi * ci.residual().flatten() for wi, ci in zip(self._weights, self._contributions.values())] + ) # Calculate the point-average chi^2 - w = dot(chiv, chiv)/len(chiv) + w = dot(chiv, chiv) / len(chiv) # Now we must append the restraints - penalties = [ sqrt(res.penalty(w)) for res in self._restraintlist ] - chiv = concatenate( [ chiv, penalties ] ) + penalties = [sqrt(res.penalty(w)) for res in self._restraintlist] + chiv = concatenate([chiv, penalties]) for fithook in self.fithooks: fithook.postcall(self, chiv) return chiv - def scalarResidual(self, p = []): + def scalarResidual(self, p=[]): """Calculate the scalar residual to be optimized. Arguments @@ -267,7 +270,7 @@ def scalarResidual(self, p = []): chiv = self.residual(p) return dot(chiv, chiv) - def __call__(self, p = []): + def __call__(self, p=[]): """Same as scalarResidual method.""" return self.scalarResidual(p) @@ -318,14 +321,12 @@ def __verifyProfiles(self): # Check for profile values for con in self._contributions.values(): if con.profile is None: - m = "FitContribution '%s' does not have a Profile"%con.name + m = "FitContribution '%s' does not have a Profile" % con.name raise AttributeError(m) - if con.profile.x is None or\ - con.profile.y is None or\ - con.profile.dy is None: + if con.profile.x is None or con.profile.y is None or con.profile.dy is None: - m = "Profile for '%s' is missing data"%con.name - raise AttributeError(m) + m = "Profile for '%s' is missing data" % con.name + raise AttributeError(m) return def __verifyParameters(self): @@ -344,7 +345,7 @@ def __verifyParameters(self): for par in badpars: objlist = self._locateManagedObject(par) names = [obj.name for obj in objlist] - badnames.append( ".".join(names) ) + badnames.append(".".join(names)) # Construct an error message, if necessary m = "" @@ -362,14 +363,15 @@ def __verifyParameters(self): def __collectConstraintsAndRestraints(self): """Collect the Constraints and Restraints from subobjects.""" - from itertools import chain from functools import cmp_to_key + from itertools import chain + rset = set(self._restraints) cdict = {} for org in chain(self._contributions.values(), self._parsets.values()): - rset.update( org._getRestraints() ) - cdict.update( org._getConstraints() ) + rset.update(org._getRestraints()) + cdict.update(org._getConstraints()) cdict.update(self._constraints) # The order of the restraint list does not matter @@ -386,7 +388,7 @@ def __collectConstraintsAndRestraints(self): # Now check the constraint's equation for constrained arguments for arg in con.eq.args: if arg in cdict: - depmap[con].add( cdict[arg] ) + depmap[con].add(cdict[arg]) # Turn the dependency map into multi-level map. def _extendDeps(con): @@ -422,8 +424,7 @@ def cmp(x, y): # Variable manipulation - def addVar(self, par, value = None, name = None, fixed = False, tag = None, - tags = []): + def addVar(self, par, value=None, name=None, fixed=False, tag=None, tags=[]): """Add a variable to be refined. par -- A Parameter that will be varied during a fit. @@ -448,10 +449,10 @@ def addVar(self, par, value = None, name = None, fixed = False, tag = None, name = name or par.name if par.const: - raise ValueError("The parameter '%s' is constant"%par) + raise ValueError("The parameter '%s' is constant" % par) if par.constrained: - raise ValueError("The parameter '%s' is constrained"%par) + raise ValueError("The parameter '%s' is constrained" % par) var = ParameterProxy(name, par) if value is not None: @@ -487,13 +488,12 @@ def delVar(self, var): def __delattr__(self, name): if name in self._parameters: - self.delVar( self._parameters[name] ) + self.delVar(self._parameters[name]) return super(FitRecipe, self).__delattr__(name) return - - def newVar(self, name, value = None, fixed = False, tag = None, tags = []): + def newVar(self, name, value=None, fixed=False, tag=None, tags=[]): """Create a new variable of the fit. This method lets new variables be created that are not tied to a @@ -543,7 +543,6 @@ def _newParameter(self, name, value, check=True): self.fix(par.name) return par - def __getVarAndCheck(self, var): """Get the actual variable from var @@ -579,14 +578,14 @@ def __getVarsFromArgs(self, *args, **kw): badtags = strargs - alltags if badtags: names = ",".join(badtags) - raise ValueError("Variables or tags cannot be found (%s)"% names) + raise ValueError("Variables or tags cannot be found (%s)" % names) # Check that variables are valid allvars = set(self._parameters.values()) badvars = varargs - allvars if badvars: names = ",".join(v.name for v in badvars) - raise ValueError("Variables cannot be found (%s)"% names) + raise ValueError("Variables cannot be found (%s)" % names) # Make sure that we only have parameters in kw kwnames = set(kw.keys()) @@ -594,7 +593,7 @@ def __getVarsFromArgs(self, *args, **kw): badkw = kwnames - allnames if badkw: names = ",".join(badkw) - raise ValueError("Tags cannot be passed as keywords (%s)"% names) + raise ValueError("Tags cannot be passed as keywords (%s)" % names) # Now get all the objects referred to in the arguments. varargs |= self._tagmanager.union(*strargs) @@ -616,7 +615,6 @@ def fix(self, *args, **kw): # Check the inputs and get the variables from them varargs = self.__getVarsFromArgs(*args, **kw) - # Fix all of these for var in varargs: self._tagmanager.tag(var, self._fixedtag) @@ -656,7 +654,7 @@ def free(self, *args, **kw): def isFree(self, var): """Check if a variable is fixed.""" - return (not self._tagmanager.hasTags(var, self._fixedtag)) + return not self._tagmanager.hasTags(var, self._fixedtag) def unconstrain(self, *pars): """Unconstrain a Parameter. @@ -692,7 +690,7 @@ def unconstrain(self, *pars): return - def constrain(self, par, con, ns = {}): + def constrain(self, par, con, ns={}): """Constrain a parameter to an equation. Note that only one constraint can exist on a Parameter at a time. @@ -722,13 +720,13 @@ def constrain(self, par, con, ns = {}): if par is None: par = ns.get(name) if par is None: - raise ValueError("The parameter '%s' cannot be found"%name) + raise ValueError("The parameter '%s' cannot be found" % name) if con in self._parameters.keys(): con = self._parameters[con] if par.const: - raise ValueError("The parameter '%s' is constant"%par) + raise ValueError("The parameter '%s' is constant" % par) # This will pass the value of a constrained parameter to the initial # value of a parameter constraint. @@ -744,11 +742,9 @@ def constrain(self, par, con, ns = {}): RecipeOrganizer.constrain(self, par, con, ns) return - def getValues(self): """Get the current values of the variables in a list.""" - return array([v.value for v in self._parameters.values() if - self.isFree(v)]) + return array([v.value for v in self._parameters.values() if self.isFree(v)]) def getNames(self): """Get the names of the variables in a list.""" @@ -772,7 +768,7 @@ def getBounds2(self): ub = array([b[1] for b in bounds]) return lb, ub - def boundsToRestraints(self, sig = 1, scaled = False): + def boundsToRestraints(self, sig=1, scaled=False): """Turn all bounded parameters into restraints. The bounds become limits on the restraint. @@ -785,13 +781,13 @@ def boundsToRestraints(self, sig = 1, scaled = False): if not hasattr(sig, "__iter__"): sig = [sig] * len(pars) for par, x in zip(pars, sig): - self.restrain(par, par.bounds[0], par.bounds[1], sig = x, - scaled = scaled) + self.restrain(par, par.bounds[0], par.bounds[1], sig=x, scaled=scaled) return def _applyValues(self, p): """Apply variable values to the variables.""" - if len(p) == 0: return + if len(p) == 0: + return vargen = (v for v in self._parameters.values() if self.isFree(v)) for var, pval in zip(vargen, p): var.setValue(pval) @@ -802,4 +798,5 @@ def _updateConfiguration(self): self._ready = False return + # End of file diff --git a/src/diffpy/srfit/fitbase/fitresults.py b/src/diffpy/srfit/fitbase/fitresults.py index 6cde340d..e01aa300 100644 --- a/src/diffpy/srfit/fitbase/fitresults.py +++ b/src/diffpy/srfit/fitbase/fitresults.py @@ -25,12 +25,13 @@ __all__ = ["FitResults", "ContributionResults", "initializeRecipe"] import re -import numpy from collections import OrderedDict -from diffpy.srfit.util.inpututils import inputToString +import numpy + from diffpy.srfit.util import _DASHEDLINE from diffpy.srfit.util import sortKeyForNumericString as numstr +from diffpy.srfit.util.inpututils import inputToString class FitResults(object): @@ -70,8 +71,7 @@ class FitResults(object): """ - def __init__(self, recipe, update = True, showfixed = True, showcon = - False): + def __init__(self, recipe, update=True, showfixed=True, showcon=False): """Initialize the attributes. recipe -- The recipe containing the results @@ -139,8 +139,7 @@ def update(self): self._calculateCovariance() # Get the variable uncertainties - self.varunc = [self.cov[i,i]**0.5 for i in \ - range(len(self.varnames))] + self.varunc = [self.cov[i, i] ** 0.5 for i in range(len(self.varnames))] # Get the constraint uncertainties self._calculateConstraintUncertainties() @@ -170,8 +169,8 @@ def _calculateCovariance(self): """ try: J = self._calculateJacobian() - u,s,vh = numpy.linalg.svd(J,0) - self.cov = numpy.dot(vh.T.conj()/s**2,vh) + u, s, vh = numpy.linalg.svd(J, 0) + self.cov = numpy.dot(vh.T.conj() / s**2, vh) except numpy.linalg.LinAlgError: self.messages.append("Cannot compute covariance matrix.") l = len(self.varvals) @@ -207,7 +206,7 @@ def _calculateJacobian(self): # The list of constraint derivatives with respect to variables # The forward difference would be faster, but perhaps not as accurate. conr = [] - for k,v in enumerate(pvals): + for k, v in enumerate(pvals): h = delta[k] pvals[k] = v + h rk = self.recipe.residual(pvals) @@ -227,14 +226,14 @@ def _calculateJacobian(self): val = con.par.getValue() if numpy.isscalar(val): cond[i] -= con.par.getValue() - cond[i] /= 2*h + cond[i] /= 2 * h else: cond[i] = 0.0 conr.append(cond) pvals[k] = v - r.append(rk/(2*h)) + r.append(rk / (2 * h)) # Reset the constrained parameters to their original values for con in recipe._oconstraints: @@ -294,7 +293,7 @@ def _calculateConstraintUncertainties(self): self.conunc.append(sig2c**0.5) return - def formatResults(self, header = "", footer = "", update = False): + def formatResults(self, header="", footer="", update=False): """Format the results and return them in a string. This function is called by printResults and saveResults. Overloading @@ -313,7 +312,7 @@ def formatResults(self, header = "", footer = "", update = False): lines = [] corrmin = 0.25 p = self.precision - pe = "%-" + "%i.%ie" % (p+6, p) + pe = "%-" + "%i.%ie" % (p + 6, p) pet = "%" + ".%ie" % (p,) # Check to see if the uncertainty values are reliable. certain = True @@ -340,12 +339,12 @@ def formatResults(self, header = "", footer = "", update = False): lines.append(l) lines.append(_DASHEDLINE) formatstr = "%-14s %.8f" - lines.append(formatstr%("Residual",self.residual)) - lines.append(formatstr%("Contributions", self.residual - self.penalty)) - lines.append(formatstr%("Restraints", self.penalty)) - lines.append(formatstr%("Chi2",self.chi2)) - lines.append(formatstr%("Reduced Chi2",self.rchi2)) - lines.append(formatstr%("Rw",self.rw)) + lines.append(formatstr % ("Residual", self.residual)) + lines.append(formatstr % ("Contributions", self.residual - self.penalty)) + lines.append(formatstr % ("Restraints", self.penalty)) + lines.append(formatstr % ("Chi2", self.chi2)) + lines.append(formatstr % ("Reduced Chi2", self.rchi2)) + lines.append(formatstr % ("Rw", self.rw)) ## Per-FitContribution results if len(self.conresults) > 1: @@ -362,12 +361,12 @@ def formatResults(self, header = "", footer = "", update = False): for name in keys: res = self.conresults[name] lines.append("") - namestr = name + " (%f)"%res.weight + namestr = name + " (%f)" % res.weight lines.append(namestr) - lines.append("-"*len(namestr)) - lines.append(formatstr%("Residual",res.residual)) - lines.append(formatstr%("Chi2",res.chi2)) - lines.append(formatstr%("Rw",res.rw)) + lines.append("-" * len(namestr)) + lines.append(formatstr % ("Residual", res.residual)) + lines.append(formatstr % ("Chi2", res.chi2)) + lines.append(formatstr % ("Rw", res.rw)) ## The variables if self.varnames: @@ -375,7 +374,7 @@ def formatResults(self, header = "", footer = "", update = False): l = "Variables" if not certain: m = "Uncertainties invalid" - l += " (%s)"%m + l += " (%s)" % m lines.append(l) lines.append(_DASHEDLINE) @@ -385,11 +384,11 @@ def formatResults(self, header = "", footer = "", update = False): varlines = [] w = max(map(len, varnames)) - w = str(w+1) + w = str(w + 1) # Format the lines - formatstr = "%-"+w+"s " + pe + " +/- " + pet + formatstr = "%-" + w + "s " + pe + " +/- " + pet for name, val, unc in zip(varnames, varvals, varunc): - varlines.append(formatstr%(name, val, unc)) + varlines.append(formatstr % (name, val, unc)) varlines.sort() lines.extend(varlines) @@ -401,14 +400,13 @@ def formatResults(self, header = "", footer = "", update = False): lines.append("Fixed Variables") lines.append(_DASHEDLINE) w = max(map(len, self.fixednames)) - w = str(w+1) - formatstr = "%-"+w+"s " + pet + w = str(w + 1) + formatstr = "%-" + w + "s " + pet for name, val in zip(self.fixednames, self.fixedvals): - varlines.append(formatstr%(name, val)) + varlines.append(formatstr % (name, val)) varlines.sort() lines.extend(varlines) - ## The constraints if self.connames and self.showcon: lines.append("") @@ -432,16 +430,16 @@ def formatResults(self, header = "", footer = "", update = False): vals[name] = (val, unc) keys.sort(key=numstr) - w = str(w+1) - formatstr = "%-"+w+"s %- 15f +/- %-15f" + w = str(w + 1) + formatstr = "%-" + w + "s %- 15f +/- %-15f" for name in keys: val, unc = vals[name] - lines.append(formatstr%(name, val, unc)) + lines.append(formatstr % (name, val, unc)) ## Variable correlations lines.append("") - corint = int(corrmin*100) - l = "Variable Correlations greater than %i%%"%corint + corint = int(corrmin * 100) + l = "Variable Correlations greater than %i%%" % corint if not certain: l += " (Correlations invalid)" lines.append(l) @@ -451,33 +449,32 @@ def formatResults(self, header = "", footer = "", update = False): n = len(self.varnames) for i in range(n): for j in range(i + 1, n): - name = "corr(%s, %s)"%(varnames[i], varnames[j]) - val = (self.cov[i,j]/(self.cov[i,i] * self.cov[j,j])**0.5) + name = "corr(%s, %s)" % (varnames[i], varnames[j]) + val = self.cov[i, j] / (self.cov[i, i] * self.cov[j, j]) ** 0.5 if abs(val) > corrmin: cornames.append(name) tup.append((val, name)) - tup.sort(key=lambda vn : abs(vn[0])) + tup.sort(key=lambda vn: abs(vn[0])) tup.reverse() if cornames: w = max(map(len, cornames)) w = str(w + 1) - formatstr = "%-"+w+"s %.4f" + formatstr = "%-" + w + "s %.4f" for val, name in tup: - lines.append(formatstr%(name, val)) + lines.append(formatstr % (name, val)) else: - lines.append("No correlations greater than %i%%"%corint) - + lines.append("No correlations greater than %i%%" % corint) # User-defined footer if footer: lines.append(footer) - out = "\n".join(lines) + '\n' + out = "\n".join(lines) + "\n" return out - def printResults(self, header = "", footer = "", update = False): + def printResults(self, header="", footer="", update=False): """Format and print the results. header -- A header to add to the output (default "") @@ -491,8 +488,7 @@ def printResults(self, header = "", footer = "", update = False): def __str__(self): return self.formatResults() - - def saveResults(self, filename, header = "", footer = "", update = False): + def saveResults(self, filename, header="", footer="", update=False): """Format and save the results. filename - Name of the save file. @@ -502,20 +498,23 @@ def saveResults(self, filename, header = "", footer = "", update = False): """ # Save the time and user - from time import ctime from getpass import getuser + from time import ctime + myheader = "Results written: " + ctime() + "\n" myheader += "produced by " + getuser() + "\n" header = myheader + header res = self.formatResults(header, footer, update) - f = open(filename, 'w') + f = open(filename, "w") f.write(res) f.close() return + # End class FitResults + class ContributionResults(object): """Class for processing, storing FitContribution results. @@ -609,13 +608,14 @@ def _calculateMetrics(self): # We take absolute values in case the signal is complex num = numpy.abs(self.y - self.ycalc) y = numpy.abs(self.y) - chiv = num/self.dy + chiv = num / self.dy self.cumchi2 = numpy.cumsum(chiv**2) # avoid index error for empty array self.chi2 = self.cumchi2[-1:].sum() yw = y / self.dy yw2tot = numpy.dot(yw, yw) - if yw2tot == 0.0: yw2tot = 1.0 + if yw2tot == 0.0: + yw2tot = 1.0 self.cumrw = numpy.sqrt(self.cumchi2 / yw2tot) # avoid index error for empty array self.rw = self.cumrw[-1:].sum() @@ -624,6 +624,7 @@ def _calculateMetrics(self): # End class ContributionResults + def resultsDictionary(results): """Get dictionary of results from file. @@ -636,8 +637,7 @@ def resultsDictionary(results): """ resstr = inputToString(results) - rx = {'f' : r"[+-]? *(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?", - 'n' : r'[a-zA-Z_]\w*'} + rx = {"f": r"[+-]? *(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?", "n": r"[a-zA-Z_]\w*"} pat = r"(%(n)s)\s+(%(f)s)" % rx matches = re.findall(pat, resstr) @@ -646,6 +646,7 @@ def resultsDictionary(results): mpairs = dict(matches) return mpairs + def initializeRecipe(recipe, results): """Initialize the variables of a recipe from a results file. diff --git a/src/diffpy/srfit/fitbase/parameter.py b/src/diffpy/srfit/fitbase/parameter.py index 277bfc52..8ef3b083 100644 --- a/src/diffpy/srfit/fitbase/parameter.py +++ b/src/diffpy/srfit/fitbase/parameter.py @@ -29,12 +29,12 @@ import numpy -from diffpy.srfit.exceptions import SrFitError from diffpy.srfit.equation.literals import Argument -from diffpy.srfit.util.nameutils import validateName -from diffpy.srfit.util.argbinders import bind2nd -from diffpy.srfit.interface import _parameter_interface +from diffpy.srfit.exceptions import SrFitError from diffpy.srfit.fitbase.validatable import Validatable +from diffpy.srfit.interface import _parameter_interface +from diffpy.srfit.util.argbinders import bind2nd +from diffpy.srfit.util.nameutils import validateName class Parameter(_parameter_interface, Argument, Validatable): @@ -53,7 +53,7 @@ class Parameter(_parameter_interface, Argument, Validatable): """ - def __init__(self, name, value = None, const = False): + def __init__(self, name, value=None, const=False): """Initialization. name -- The name of this Parameter (must be a valid attribute @@ -86,7 +86,7 @@ def setValue(self, val): Argument.setValue(self, val) return self - def setConst(self, const = True, value = None): + def setConst(self, const=True, value=None): """Toggle the Parameter as constant. const -- Flag indicating if the parameter is constant (default @@ -103,7 +103,6 @@ def setConst(self, const = True, value = None): self.setValue(value) return self - def boundRange(self, lb=None, ub=None): """Set lower and upper bound of the Parameter. @@ -118,8 +117,7 @@ def boundRange(self, lb=None, ub=None): self.bounds[1] = ub return self - - def boundWindow(self, lr = 0, ur = None): + def boundWindow(self, lr=0, ur=None): """Create bounds centered on the current value of the Parameter. lr -- The radius of the lower bound (default 0). The lower bound is @@ -148,11 +146,13 @@ def _validate(self): """ if self.value is None: - raise SrFitError("value of '%s' is None"%self.name) + raise SrFitError("value of '%s' is None" % self.name) return + # End class Parameter + class ParameterProxy(Parameter): """A Parameter proxy for another parameter. @@ -165,7 +165,6 @@ class ParameterProxy(Parameter): """ - def __init__(self, name, par): """Initialization. @@ -185,8 +184,7 @@ def __init__(self, name, par): @property def constrained(self): - """A flag indicating if the proxied Parameter is constrained. - """ + """A flag indicating if the proxied Parameter is constrained.""" return self.par.constrained @constrained.setter @@ -194,7 +192,6 @@ def constrained(self, value): self.par.constrained = bool(value) return - @property def bounds(self): """List of lower and upper bounds of the proxied Parameter. @@ -209,7 +206,6 @@ def bounds(self, value): self.par.bounds = value return - @property def _observers(self): return self.par._observers @@ -220,27 +216,22 @@ def _observers(self): def setValue(self, val): return self.par.setValue(val) - @wraps(Parameter.getValue) def getValue(self): return self.par.getValue() - @wraps(Parameter.setConst) def setConst(self, const=True, value=None): return self.par.setConst(const, value) - @wraps(Parameter.boundRange) def boundRange(self, lb=None, ub=None): return self.par.boundRange(lb, ub) - @wraps(Parameter.boundWindow) def boundWindow(self, lr=0, ur=None): return self.par.boundWindow(lr, ur) - def _validate(self): """Validate my state. @@ -254,6 +245,7 @@ def _validate(self): self.par._validate() return + # End class ParameterProxy @@ -265,7 +257,7 @@ class ParameterAdapter(Parameter): """ - def __init__(self, name, obj, getter = None, setter = None, attr = None): + def __init__(self, name, obj, getter=None, setter=None, attr=None): """Wrap an object as a Parameter. name -- The name of this Parameter. @@ -326,6 +318,7 @@ def setValue(self, value): self.notify() return self + # End class ParameterAdapter # End of file diff --git a/src/diffpy/srfit/fitbase/parameterset.py b/src/diffpy/srfit/fitbase/parameterset.py index a13d7ea5..ef64c8e9 100644 --- a/src/diffpy/srfit/fitbase/parameterset.py +++ b/src/diffpy/srfit/fitbase/parameterset.py @@ -98,7 +98,7 @@ def removeParameterSet(self, parset): self._removeObject(parset, self._parsets) return - def setConst(self, const = True): + def setConst(self, const=True): """Set every parameter within the set to a constant. const -- Flag indicating if the parameter is constant (default @@ -110,6 +110,7 @@ def setConst(self, const = True): return + # End class ParameterSet # End of file diff --git a/src/diffpy/srfit/fitbase/profile.py b/src/diffpy/srfit/fitbase/profile.py index 292fdb89..02145e93 100644 --- a/src/diffpy/srfit/fitbase/profile.py +++ b/src/diffpy/srfit/fitbase/profile.py @@ -23,13 +23,13 @@ __all__ = ["Parameter", "Profile"] -import six import numpy +import six -from diffpy.srfit.util.observable import Observable +from diffpy.srfit.exceptions import SrFitError from diffpy.srfit.fitbase.parameter import Parameter from diffpy.srfit.fitbase.validatable import Validatable -from diffpy.srfit.exceptions import SrFitError +from diffpy.srfit.util.observable import Observable # This is the roundoff tolerance for selecting bounds on arrays. epsilon = 1e-8 @@ -88,19 +88,15 @@ def __init__(self): return # We want x, y, ycalc and dy to stay in-sync with xpar, ypar and dypar - x = property( lambda self : self.xpar.getValue(), - lambda self, val : self.xpar.setValue(val) ) - y = property( lambda self : self.ypar.getValue(), - lambda self, val : self.ypar.setValue(val) ) - dy = property( lambda self : self.dypar.getValue(), - lambda self, val : self.dypar.setValue(val) ) - ycalc = property( lambda self : self.ycpar.getValue(), - lambda self, val : self.ycpar.setValue(val) ) + x = property(lambda self: self.xpar.getValue(), lambda self, val: self.xpar.setValue(val)) + y = property(lambda self: self.ypar.getValue(), lambda self, val: self.ypar.setValue(val)) + dy = property(lambda self: self.dypar.getValue(), lambda self, val: self.dypar.setValue(val)) + ycalc = property(lambda self: self.ycpar.getValue(), lambda self, val: self.ycpar.setValue(val)) # We want xobs, yobs and dyobs to be read-only - xobs = property( lambda self: self._xobs ) - yobs = property( lambda self: self._yobs ) - dyobs = property( lambda self: self._dyobs ) + xobs = property(lambda self: self._xobs) + yobs = property(lambda self: self._yobs) + dyobs = property(lambda self: self._dyobs) def loadParsedData(self, parser): """Load parsed data from a ProfileParser. @@ -113,7 +109,7 @@ def loadParsedData(self, parser): self.setObservedProfile(x, y, dy) return - def setObservedProfile(self, xobs, yobs, dyobs = None): + def setObservedProfile(self, xobs, yobs, dyobs=None): """Set the observed profile. Arguments @@ -182,29 +178,27 @@ def setCalculationRange(self, xmin=None, xmax=None, dx=None): """ if self.xobs is None: raise AttributeError("No observed profile") + # local helper function def _isobs(a): if not isinstance(a, six.string_types): return False - if a != 'obs': + if a != "obs": raise ValueError('Must be either float or "obs".') return True + # resolve new low and high bounds for x - lo = (self.x[0] if xmin is None else - self.xobs[0] if _isobs(xmin) else float(xmin)) + lo = self.x[0] if xmin is None else self.xobs[0] if _isobs(xmin) else float(xmin) lo = max(lo, self.xobs[0]) - hi = (self.x[-1] if xmax is None else - self.xobs[-1] if _isobs(xmax) else float(xmax)) + hi = self.x[-1] if xmax is None else self.xobs[-1] if _isobs(xmax) else float(xmax) hi = min(hi, self.xobs[-1]) # determine if we need to clip the original grid clip = True step = None ncur = len(self.x) - stepcur = (1 if ncur < 2 - else (self.x[-1] - self.x[0]) / (ncur - 1.0)) + stepcur = 1 if ncur < 2 else (self.x[-1] - self.x[0]) / (ncur - 1.0) nobs = len(self.xobs) - stepobs = (1 if nobs < 2 - else (self.xobs[-1] - self.xobs[0]) / (nobs - 1.0)) + stepobs = 1 if nobs < 2 else (self.xobs[-1] - self.xobs[0]) / (nobs - 1.0) if dx is None: # check if xobs overlaps with x i0 = numpy.fabs(self.xobs - self.x[0]).argmin() @@ -244,7 +238,6 @@ def _isobs(a): self.setCalculationPoints(x1) return - def setCalculationPoints(self, x): """Set the calculation points. @@ -258,8 +251,8 @@ def setCalculationPoints(self, x): """ x = numpy.asarray(x) if self.xobs is not None: - x = x[ x >= self.xobs[0] - epsilon ] - x = x[ x <= self.xobs[-1] + epsilon ] + x = x[x >= self.xobs[0] - epsilon] + x = x[x <= self.xobs[-1] + epsilon] self.x = x if self.yobs is not None: self.y = rebinArray(self.yobs, self.xobs, self.x) @@ -268,8 +261,8 @@ def setCalculationPoints(self, x): if (self.dyobs == 1).all(): self.dy = numpy.ones_like(self.x) else: - # FIXME - This does not follow error propogation rules and it - # introduces (more) correlation between the data points. + # FIXME - This does not follow error propogation rules and it + # introduces (more) correlation between the data points. self.dy = rebinArray(self.dyobs, self.xobs, self.x) return @@ -309,7 +302,6 @@ def loadtxt(self, *args, **kw): self.setObservedProfile(x, y, dy) return x, y, dy - def savetxt(self, fname, **kwargs): """Call `numpy.savetxt` with x, ycalc, y, dy. @@ -337,12 +329,11 @@ def savetxt(self, fname, **kwargs): raise SrFitError("ycalc is None") y = self.y dy = self.dy - kwargs.setdefault('header', 'x ycalc y dy') + kwargs.setdefault("header", "x ycalc y dy") data = numpy.transpose([x, ycalc, y, dy]) numpy.savetxt(fname, data, **kwargs) return - def _flush(self, other): """Invalidate cached state. @@ -362,8 +353,7 @@ def _validate(self): Raises SrFitError if validation fails. """ - datanotset = any(v is None for v in - [self.x, self.y, self.dy, self.xobs, self.yobs, self.dyobs]) + datanotset = any(v is None for v in [self.x, self.y, self.dy, self.xobs, self.yobs, self.dyobs]) if datanotset: raise SrFitError("Missing data") if len(self.x) != len(self.y) or len(self.x) != len(self.dy): @@ -373,6 +363,7 @@ def _validate(self): # End class Profile + def rebinArray(A, xold, xnew): """Rebin the an array by interpolating over the new x range. diff --git a/src/diffpy/srfit/fitbase/profilegenerator.py b/src/diffpy/srfit/fitbase/profilegenerator.py index 5d0fed84..80a5958b 100644 --- a/src/diffpy/srfit/fitbase/profilegenerator.py +++ b/src/diffpy/srfit/fitbase/profilegenerator.py @@ -45,8 +45,8 @@ from diffpy.srfit.equation.literals.operators import Operator -from diffpy.srfit.fitbase.parameterset import ParameterSet from diffpy.srfit.exceptions import SrFitError +from diffpy.srfit.fitbase.parameterset import ParameterSet class ProfileGenerator(Operator, ParameterSet): @@ -95,7 +95,6 @@ class ProfileGenerator(Operator, ParameterSet): nin = 0 nout = 1 - def __init__(self, name): """Initialize the attributes.""" Operator.__init__(self) @@ -104,7 +103,6 @@ def __init__(self, name): self.meta = {} return - @property def symbol(self): return self.name @@ -131,7 +129,6 @@ def operation(self): y = self.__call__(self.profile.x) return y - def setProfile(self, profile): """Assign the profile. @@ -147,7 +144,7 @@ def setProfile(self, profile): self._flush(other=(self,)) # Merge the profiles metadata with our own - self.meta.update( self.profile.meta ) + self.meta.update(self.profile.meta) self.processMetaData() return diff --git a/src/diffpy/srfit/fitbase/profileparser.py b/src/diffpy/srfit/fitbase/profileparser.py index 8dff0cf2..40812224 100644 --- a/src/diffpy/srfit/fitbase/profileparser.py +++ b/src/diffpy/srfit/fitbase/profileparser.py @@ -105,7 +105,7 @@ def parseFile(self, filename): Raises ParseError if the file cannot be parsed """ - infile = open(filename, 'r') + infile = open(filename, "r") self._banks = [] self._meta = {} filestring = infile.read() @@ -155,7 +155,7 @@ def selectBank(self, index): self._x, self._y, self._dx, self._dy = self._banks[index] return - def getData(self, index = None): + def getData(self, index=None): """Get the data. This method should only be called after the data has been parsed. The @@ -179,4 +179,5 @@ def getMetaData(self): """Get the parsed metadata.""" return self._meta + # End of ProfileParser diff --git a/src/diffpy/srfit/fitbase/recipeorganizer.py b/src/diffpy/srfit/fitbase/recipeorganizer.py index e3c95267..bbec6072 100644 --- a/src/diffpy/srfit/fitbase/recipeorganizer.py +++ b/src/diffpy/srfit/fitbase/recipeorganizer.py @@ -23,26 +23,25 @@ __all__ = ["RecipeContainer", "RecipeOrganizer", "equationFromString"] -from numpy import inf +import re from collections import OrderedDict from itertools import chain, groupby -import re import six +from numpy import inf +from diffpy.srfit.equation import Equation +from diffpy.srfit.equation.builder import EquationFactory +from diffpy.srfit.fitbase.configurable import Configurable from diffpy.srfit.fitbase.constraint import Constraint -from diffpy.srfit.fitbase.restraint import Restraint from diffpy.srfit.fitbase.parameter import Parameter -from diffpy.srfit.fitbase.configurable import Configurable +from diffpy.srfit.fitbase.restraint import Restraint from diffpy.srfit.fitbase.validatable import Validatable - -from diffpy.srfit.util.observable import Observable -from diffpy.srfit.equation import Equation -from diffpy.srfit.equation.builder import EquationFactory -from diffpy.srfit.util.nameutils import validateName from diffpy.srfit.interface import _recipeorganizer_interface from diffpy.srfit.util import _DASHEDLINE from diffpy.srfit.util import sortKeyForNumericString as numstr +from diffpy.srfit.util.nameutils import validateName +from diffpy.srfit.util.observable import Observable class RecipeContainer(Observable, Configurable, Validatable): @@ -109,7 +108,6 @@ def _iterManaged(self): """Get iterator over managed objects.""" return chain(*(d.values() for d in self.__managed)) - def iterPars(self, pattern="", recurse=True): """Iterate over the Parameters contained in this object. @@ -137,7 +135,6 @@ def iterPars(self, pattern="", recurse=True): yield par return - def __iter__(self): """Iterate over top-level parameters.""" return iter(self._parameters.values()) @@ -158,12 +155,13 @@ def __getattr__(self, name): raise AttributeError(name) return arg - # Ensure there is no __dir__ override in the base class. - assert (getattr(Observable, '__dir__', None) is - getattr(Configurable, '__dir__', None) is - getattr(Validatable, '__dir__', None) is - getattr(object, '__dir__', None)) + assert ( + getattr(Observable, "__dir__", None) + is getattr(Configurable, "__dir__", None) + is getattr(Validatable, "__dir__", None) + is getattr(object, "__dir__", None) + ) def __dir__(self): "Return sorted list of attributes for this object." @@ -175,7 +173,6 @@ def __dir__(self): rv = sorted(rv) return rv - # Needed by __setattr__ _parameters = OrderedDict() __managed = [] @@ -192,12 +189,11 @@ def __setattr__(self, name, value): m = self.get(name) if m is not None: - raise AttributeError("Cannot set '%s'"%name) + raise AttributeError("Cannot set '%s'" % name) super(RecipeContainer, self).__setattr__(name, value) return - def __delattr__(self, name): """Delete parameters with del. @@ -205,17 +201,17 @@ def __delattr__(self, name): configuration changes that are not yet handled in a general way. """ if name in self._parameters: - self._removeParameter( self._parameters[name] ) + self._removeParameter(self._parameters[name]) return m = self.get(name) if m is not None: - raise AttributeError("Cannot delete '%s'"%name) + raise AttributeError("Cannot delete '%s'" % name) super(RecipeContainer, self).__delattr__(name) return - def get(self, name, default = None): + def get(self, name, default=None): """Get a managed object.""" for d in self.__managed: arg = d.get(name) @@ -232,7 +228,7 @@ def getValues(self): """Get the values of managed parameters.""" return [p.value for p in self._parameters.values()] - def _addObject(self, obj, d, check = True): + def _addObject(self, obj, d, check=True): """Add an object to a managed dictionary. obj -- The object to be stored. @@ -253,14 +249,12 @@ def _addObject(self, obj, d, check = True): # Check for extant object in d with same name oldobj = d.get(obj.name) if check and oldobj is not None: - message = "%s with name '%s' already exists"%\ - (obj.__class__.__name__, obj.name) + message = "%s with name '%s' already exists" % (obj.__class__.__name__, obj.name) raise ValueError(message) # Check for object with same name in other dictionary. if oldobj is None and self.get(obj.name) is not None: - message = "Non-%s with name '%s' already exists"%\ - (obj.__class__.__name__, obj.name) + message = "Non-%s with name '%s' already exists" % (obj.__class__.__name__, obj.name) raise ValueError(message) # Detach the old object, if there is one @@ -346,6 +340,7 @@ def _validate(self): # End class RecipeContainer + class RecipeOrganizer(_recipeorganizer_interface, RecipeContainer): """Extended base class for organizing pieces of a FitRecipe. @@ -436,7 +431,7 @@ def _removeParameter(self, par): self._eqfactory.deRegisterBuilder(par.name) return - def registerCalculator(self, f, argnames = None): + def registerCalculator(self, f, argnames=None): """Register a Calculator so it can be used within equation strings. A Calculator is an elaborate function that can organize Parameters. @@ -456,7 +451,7 @@ def registerCalculator(self, f, argnames = None): if argnames is None: fncode = f.__call__.__func__.__code__ argnames = list(fncode.co_varnames) - argnames = argnames[1:fncode.co_argcount] + argnames = argnames[1 : fncode.co_argcount] for pname in argnames: if pname not in self._eqfactory.builders: @@ -469,7 +464,7 @@ def registerCalculator(self, f, argnames = None): eq = self._eqfactory.makeEquation(f.name) return eq - def registerFunction(self, f, name = None, argnames = None): + def registerFunction(self, f, name=None, argnames=None): """Register a function so it can be used within equation strings. This creates a function with this class that can be used within string @@ -523,12 +518,12 @@ def registerFunction(self, f, name = None, argnames = None): fncode = f.__code__ # check class method elif inspect.ismethod(f): - fncode = f.__func__.__code__ - offset = 1 + fncode = f.__func__.__code__ + offset = 1 # check functor - elif hasattr(f, "__call__") and hasattr(f.__call__, '__func__'): - fncode = f.__call__.__func__.__code__ - offset = 1 + elif hasattr(f, "__call__") and hasattr(f.__call__, "__func__"): + fncode = f.__call__.__func__.__code__ + offset = 1 else: m = "Cannot extract name or argnames" raise ValueError(m) @@ -536,14 +531,14 @@ def registerFunction(self, f, name = None, argnames = None): # Extract the name if name is None: name = fncode.co_name - if name == '': + if name == "": m = "You must supply a name name for a lambda function" raise ValueError(m) # Extract the arguments if argnames is None: argnames = list(fncode.co_varnames) - argnames = argnames[offset:fncode.co_argcount] + argnames = argnames[offset : fncode.co_argcount] #### End introspection code @@ -554,6 +549,7 @@ def registerFunction(self, f, name = None, argnames = None): # Initialize and register from diffpy.srfit.fitbase.calculator import Calculator + if isinstance(f, Calculator): for pname in argnames: par = self.get(pname) @@ -567,7 +563,7 @@ def registerFunction(self, f, name = None, argnames = None): return eq - def registerStringFunction(self, fstr, name, ns = {}): + def registerStringFunction(self, fstr, name, ns={}): """Register a string function. This creates a function with this class that can be used within string @@ -589,8 +585,7 @@ def registerStringFunction(self, fstr, name, ns = {}): """ # Build the equation instance. - eq = equationFromString(fstr, self._eqfactory, ns = ns, buildargs = - True) + eq = equationFromString(fstr, self._eqfactory, ns=ns, buildargs=True) eq.name = name # Register any new Parameters. @@ -601,8 +596,7 @@ def registerStringFunction(self, fstr, name, ns = {}): argnames = eq.argdict.keys() return self.registerFunction(eq, name, argnames) - - def evaluateEquation(self, eqstr, ns = {}): + def evaluateEquation(self, eqstr, ns={}): """Evaluate a string equation. eqstr -- A string equation to evaluate. The equation is evaluated at @@ -620,8 +614,7 @@ def evaluateEquation(self, eqstr, ns = {}): self._eqfactory.wipeout(eq) return rv - - def constrain(self, par, con, ns = {}): + def constrain(self, par, con, ns={}): """Constrain a parameter to an equation. Note that only one constraint can exist on a Parameter at a time. @@ -651,16 +644,16 @@ def constrain(self, par, con, ns = {}): raise ValueError("The parameter cannot be found") if par.const: - raise ValueError("The parameter '%s' is constant"%par) + raise ValueError("The parameter '%s' is constant" % par) if isinstance(con, six.string_types): eqstr = con eq = equationFromString(con, self._eqfactory, ns) else: - eq = Equation(root = con) + eq = Equation(root=con) eqstr = con.name - eq.name = "_constraint_%s"%par.name + eq.name = "_constraint_%s" % par.name # Make and store the constraint con = Constraint() @@ -683,7 +676,7 @@ def isConstrained(self, par): name = par par = self.get(name) - return (par in self._constraints) + return par in self._constraints def unconstrain(self, *pars): """Unconstrain a Parameter. @@ -719,7 +712,7 @@ def unconstrain(self, *pars): return - def getConstrainedPars(self, recurse = False): + def getConstrainedPars(self, recurse=False): """Get a list of constrained managed Parameters in this object. recurse -- Recurse into managed objects and retrive their constrained @@ -728,7 +721,7 @@ def getConstrainedPars(self, recurse = False): const = self._getConstraints(recurse) return const.keys() - def clearConstraints(self, recurse = False): + def clearConstraints(self, recurse=False): """Clear all constraints managed by this organizer. recurse -- Recurse into managed objects and clear all constraints @@ -741,13 +734,12 @@ def clearConstraints(self, recurse = False): self.unconstrain(*self._constraints) if recurse: - f = lambda m : hasattr(m, "clearConstraints") + f = lambda m: hasattr(m, "clearConstraints") for m in filter(f, self._iterManaged()): m.clearConstraints(recurse) return - def restrain(self, res, lb = -inf, ub = inf, sig = 1, scaled = False, ns = - {}): + def restrain(self, res, lb=-inf, ub=inf, sig=1, scaled=False, ns={}): """Restrain an expression to specified bounds res -- An equation string or Parameter to restrain. @@ -778,7 +770,7 @@ def restrain(self, res, lb = -inf, ub = inf, sig = 1, scaled = False, ns = eqstr = res eq = equationFromString(res, self._eqfactory, ns) else: - eq = Equation(root = res) + eq = Equation(root=res) eqstr = res.name # Make and store the restraint @@ -816,7 +808,7 @@ def unrestrain(self, *ress): return - def clearRestraints(self, recurse = False): + def clearRestraints(self, recurse=False): """Clear all restraints. recurse -- Recurse into managed objects and clear all restraints @@ -825,33 +817,33 @@ def clearRestraints(self, recurse = False): self.unrestrain(*self._restraints) if recurse: - f = lambda m : hasattr(m, "clearRestraints") + f = lambda m: hasattr(m, "clearRestraints") for m in filter(f, self._iterManaged()): m.clearRestraints(recurse) return - def _getConstraints(self, recurse = True): + def _getConstraints(self, recurse=True): """Get the constrained Parameters for this and managed sub-objects.""" constraints = {} if recurse: - f = lambda m : hasattr(m, "_getConstraints") + f = lambda m: hasattr(m, "_getConstraints") for m in filter(f, self._iterManaged()): - constraints.update( m._getConstraints(recurse) ) + constraints.update(m._getConstraints(recurse)) - constraints.update( self._constraints) + constraints.update(self._constraints) return constraints - def _getRestraints(self, recurse = True): + def _getRestraints(self, recurse=True): """Get the Restraints for this and embedded ParameterSets. This returns a set of Restraint objects. """ restraints = set(self._restraints) if recurse: - f = lambda m : hasattr(m, "_getRestraints") + f = lambda m: hasattr(m, "_getRestraints") for m in filter(f, self._iterManaged()): - restraints.update( m._getRestraints(recurse) ) + restraints.update(m._getRestraints(recurse)) return restraints @@ -889,9 +881,8 @@ def _formatManaged(self, prefix=""): if self._parameters: w0 = max(len(n) for n in self._parameters) w1 = ((w0 + len(prefix) + 1) // 4 + 1) * 4 - fmt = formatstr.replace('W', str(w1)) - lines.extend(fmt.format(prefix + n, p.value) - for n, p in self._parameters.items()) + fmt = formatstr.replace("W", str(w1)) + lines.extend(fmt.format(prefix + n, p.value) for n, p in self._parameters.items()) # Recurse into managed objects. for obj in self._iterManaged(): if hasattr(obj, "_formatManaged"): @@ -901,7 +892,6 @@ def _formatManaged(self, prefix=""): lines.extend(tlines) return lines - def _formatConstraints(self): """Format constraints for showing. @@ -927,7 +917,6 @@ def _formatConstraints(self): clines.sort(key=numstr) return clines - def _formatRestraints(self): """Format restraints for showing. @@ -943,13 +932,11 @@ def _formatRestraints(self): rset = self._getRestraints() rlines = [] for res in rset: - line = "%s: lb = %f, ub = %f, sig = %f, scaled = %s"%\ - (res.eqstr, res.lb, res.ub, res.sig, res.scaled) + line = "%s: lb = %f, ub = %f, sig = %f, scaled = %s" % (res.eqstr, res.lb, res.ub, res.sig, res.scaled) rlines.append(line) rlines.sort(key=numstr) return rlines - def show(self, pattern="", textwidth=78): """Show the configuration hierarchy on the screen. @@ -965,8 +952,7 @@ def show(self, pattern="", textwidth=78): the screen width. Do not trim when negative or 0. """ regexp = re.compile(pattern) - pmatch = lambda s : (len(s.split(None, 1)) < 2 or - regexp.search(s.split(None, 1)[0])) + pmatch = lambda s: (len(s.split(None, 1)) < 2 or regexp.search(s.split(None, 1)[0])) # Show sub objects and their parameters lines = [] tlines = self._formatManaged() @@ -1007,10 +993,11 @@ def show(self, pattern="", textwidth=78): print("\n".join(s[:tw] for s in lines)) return + # End RecipeOrganizer -def equationFromString(eqstr, factory, ns = {}, buildargs = False, - argclass = Parameter, argkw = {}): + +def equationFromString(eqstr, factory, ns={}, buildargs=False, argclass=Parameter, argkw={}): """Make an equation from a string. eqstr -- A string representation of the equation. The equation must diff --git a/src/diffpy/srfit/fitbase/restraint.py b/src/diffpy/srfit/fitbase/restraint.py index 4ff2c1fa..3488e50f 100644 --- a/src/diffpy/srfit/fitbase/restraint.py +++ b/src/diffpy/srfit/fitbase/restraint.py @@ -25,8 +25,8 @@ from numpy import inf -from diffpy.srfit.fitbase.validatable import Validatable from diffpy.srfit.exceptions import SrFitError +from diffpy.srfit.fitbase.validatable import Validatable class Restraint(Validatable): @@ -49,7 +49,7 @@ class Restraint(Validatable): """ - def __init__(self, eq, lb = -inf, ub = inf, sig = 1, scaled = False): + def __init__(self, eq, lb=-inf, ub=inf, sig=1, scaled=False): """Restrain an equation to specified bounds. eq -- An equation whose evaluation is compared against the @@ -71,7 +71,7 @@ def __init__(self, eq, lb = -inf, ub = inf, sig = 1, scaled = False): self.scaled = bool(scaled) return - def penalty(self, w = 1.0): + def penalty(self, w=1.0): """Calculate the penalty of the restraint. w -- The point-average chi^2 which is optionally used to scale the @@ -81,7 +81,7 @@ def penalty(self, w = 1.0): """ val = self.eq() - penalty = (max(0, self.lb - val, val - self.ub) / self.sig)**2 + penalty = (max(0, self.lb - val, val - self.ub) / self.sig) ** 2 if self.scaled: penalty *= w @@ -99,6 +99,7 @@ def _validate(self): if self.eq is None: raise SrFitError("eq is None") from diffpy.srfit.equation.visitors import validate + try: validate(self.eq) except ValueError as e: @@ -115,6 +116,7 @@ def _validate(self): return + # End class Restraint # End of file diff --git a/src/diffpy/srfit/fitbase/simplerecipe.py b/src/diffpy/srfit/fitbase/simplerecipe.py index 9cb5cfe2..da9809c1 100644 --- a/src/diffpy/srfit/fitbase/simplerecipe.py +++ b/src/diffpy/srfit/fitbase/simplerecipe.py @@ -16,8 +16,8 @@ """Simple FitRecipe class that includes a FitContribution and Profile. """ -from diffpy.srfit.fitbase.fitrecipe import FitRecipe from diffpy.srfit.fitbase.fitcontribution import FitContribution +from diffpy.srfit.fitbase.fitrecipe import FitRecipe from diffpy.srfit.fitbase.fitresults import FitResults from diffpy.srfit.fitbase.profile import Profile @@ -68,7 +68,7 @@ class SimpleRecipe(FitRecipe): """ - def __init__(self, name = "fit", conclass = FitContribution): + def __init__(self, name="fit", conclass=FitContribution): """Initialization.""" FitRecipe.__init__(self, name) self.fithooks[0].verbose = 3 @@ -76,11 +76,10 @@ def __init__(self, name = "fit", conclass = FitContribution): self.profile = Profile() contribution.setProfile(self.profile) self.addContribution(contribution) - self.results = FitResults(self, update = False) + self.results = FitResults(self, update=False) # Adopt all the FitContribution methods - public = [aname for aname in dir(contribution) if aname not in - dir(self) and not aname.startswith("_")] + public = [aname for aname in dir(contribution) if aname not in dir(self) and not aname.startswith("_")] for mname in public: method = getattr(contribution, mname) setattr(self, mname, method) @@ -95,7 +94,7 @@ def loadParsedData(self, parser): """ return self.profile.loadParsedData(parser) - def setObservedProfile(self, xobs, yobs, dyobs = None): + def setObservedProfile(self, xobs, yobs, dyobs=None): """Set the observed profile. Arguments @@ -111,7 +110,6 @@ def setObservedProfile(self, xobs, yobs, dyobs = None): """ return self.profile.setObservedProfile(xobs, yobs, dyobs) - def setCalculationRange(self, xmin=None, xmax=None, dx=None): """Set epsilon-inclusive calculation range. @@ -146,7 +144,6 @@ def setCalculationRange(self, xmin=None, xmax=None, dx=None): """ return self.profile.setCalculationRange(xmin, xmax, dx) - def setCalculationPoints(self, x): """Set the calculation points. @@ -178,7 +175,7 @@ def loadtxt(self, *args, **kw): return self.profile.loadtxt(*args, **kw) # FitContribution - def setEquation(self, eqstr, ns = {}): + def setEquation(self, eqstr, ns={}): """Set the profile equation for the FitContribution. This sets the equation that will be used when generating the residual. @@ -195,11 +192,12 @@ def setEquation(self, eqstr, ns = {}): variable. """ - self.contribution.setEquation(eqstr, ns = {}) + self.contribution.setEquation(eqstr, ns={}) # Extract variables for par in self.contribution: # Skip Profile Parameters - if par.name in ("x", "y", "dy"): continue + if par.name in ("x", "y", "dy"): + continue if par.value is None: par.value = 0 if par.name not in self._parameters: @@ -212,7 +210,7 @@ def __call__(self): # FitResults methods - def printResults(self, header = "", footer = ""): + def printResults(self, header="", footer=""): """Format and print the results. header -- A header to add to the output (default "") @@ -222,7 +220,7 @@ def printResults(self, header = "", footer = ""): self.results.printResults(header, footer, True) return - def saveResults(self, filename, header = "", footer = ""): + def saveResults(self, filename, header="", footer=""): """Format and save the results. filename - Name of the save file. @@ -232,6 +230,7 @@ def saveResults(self, filename, header = "", footer = ""): """ self.results.saveResults(filename, header, footer, True) + # End class SimpleRecipe # End of file diff --git a/src/diffpy/srfit/fitbase/validatable.py b/src/diffpy/srfit/fitbase/validatable.py index c4db72c7..110dbbe0 100644 --- a/src/diffpy/srfit/fitbase/validatable.py +++ b/src/diffpy/srfit/fitbase/validatable.py @@ -38,7 +38,8 @@ def _validateOthers(self, iterable): """ for obj in iterable: - if obj is self: continue + if obj is self: + continue if isinstance(obj, Validatable): obj._validate() @@ -56,6 +57,7 @@ def _validate(self): # Then validate others. return + # End class Validatable # End of file diff --git a/src/diffpy/srfit/interface/__init__.py b/src/diffpy/srfit/interface/__init__.py index 8f6bd3a7..d3675428 100644 --- a/src/diffpy/srfit/interface/__init__.py +++ b/src/diffpy/srfit/interface/__init__.py @@ -22,12 +22,15 @@ from diffpy.srfit.interface.interface import ParameterInterface + _parameter_interface = ParameterInterface from diffpy.srfit.interface.interface import RecipeOrganizerInterface + _recipeorganizer_interface = RecipeOrganizerInterface from diffpy.srfit.interface.interface import FitRecipeInterface + _fitrecipe_interface = FitRecipeInterface # End of file diff --git a/src/diffpy/srfit/interface/interface.py b/src/diffpy/srfit/interface/interface.py index 94c5fb6d..31d9b869 100644 --- a/src/diffpy/srfit/interface/interface.py +++ b/src/diffpy/srfit/interface/interface.py @@ -21,8 +21,7 @@ objects. See individual interface classes for specifics. """ -__all__ = ["ParameterInterface", "FitRecipeInterface", - "RecipeOrganizerInterface"] +__all__ = ["ParameterInterface", "FitRecipeInterface", "RecipeOrganizerInterface"] import six @@ -45,10 +44,12 @@ def __lshift__(self, v): self.value = v return self + # End class ParameterInterface # ---------------------------------------------------------------------------- + class RecipeOrganizerInterface(object): """Mix-in class for enhancing the RecipeOrganizer interface.""" @@ -79,6 +80,7 @@ def __iadd__(self, args): This accepts arguments for a single function call. """ + # Want to detect _addParameter or _newParameter def f(*args): if isinstance(args[0], six.string_types): @@ -90,10 +92,12 @@ def f(*args): _applyargs(args, f) return self + # End class RecipeOrganizerInterface # ---------------------------------------------------------------------------- + class FitRecipeInterface(object): """Mix-in class for enhancing the FitRecipe interface.""" @@ -115,6 +119,7 @@ def __iadd__(self, args): This accepts a single argument or an iterable of single arguments or argument tuples. """ + # Want to detect addVar or newVar def f(*args): if isinstance(args[0], six.string_types): @@ -126,10 +131,12 @@ def f(*args): _applymanyargs(args, f) return self + # End class FitRecipeInterface # Local helper functions ----------------------------------------------------- + def _applymanyargs(args, f): """Apply arguments to a function. @@ -138,18 +145,19 @@ def _applymanyargs(args, f): (arg1, arg2, ...) ((arg1a, arg1b, ...), ...) """ - if not hasattr(args, '__iter__'): + if not hasattr(args, "__iter__"): f(args) return for arg in args: - if hasattr(arg, '__iter__'): + if hasattr(arg, "__iter__"): f(*arg) else: f(arg) return + def _applyargs(args, f): """Apply arguments to a function. @@ -158,10 +166,11 @@ def _applyargs(args, f): (arg1, arg2, ...) ((arg1a, arg1b, ...), ...) """ - if not hasattr(args, '__iter__'): + if not hasattr(args, "__iter__"): f(args) else: f(*args) return + # End of file diff --git a/src/diffpy/srfit/pdf/__init__.py b/src/diffpy/srfit/pdf/__init__.py index 956264e0..d0e7db8d 100644 --- a/src/diffpy/srfit/pdf/__init__.py +++ b/src/diffpy/srfit/pdf/__init__.py @@ -18,9 +18,9 @@ __all__ = ["PDFGenerator", "DebyePDFGenerator", "PDFContribution", "PDFParser"] -from diffpy.srfit.pdf.pdfgenerator import PDFGenerator from diffpy.srfit.pdf.debyepdfgenerator import DebyePDFGenerator from diffpy.srfit.pdf.pdfcontribution import PDFContribution +from diffpy.srfit.pdf.pdfgenerator import PDFGenerator from diffpy.srfit.pdf.pdfparser import PDFParser # End of file diff --git a/src/diffpy/srfit/pdf/basepdfgenerator.py b/src/diffpy/srfit/pdf/basepdfgenerator.py index f0f2747f..e6f6af7b 100644 --- a/src/diffpy/srfit/pdf/basepdfgenerator.py +++ b/src/diffpy/srfit/pdf/basepdfgenerator.py @@ -23,15 +23,15 @@ import numpy +from diffpy.srfit.exceptions import SrFitError from diffpy.srfit.fitbase import ProfileGenerator from diffpy.srfit.fitbase.parameter import ParameterAdapter from diffpy.srfit.structure import struToParameterSet -from diffpy.srfit.exceptions import SrFitError - # FIXME - Parameter creation will have to be smarter once deeper calculator # configuration is enabled. + class BasePDFGenerator(ProfileGenerator): """Base class for calculating PDF profiles using SrReal. @@ -74,7 +74,7 @@ class BasePDFGenerator(ProfileGenerator): """ - def __init__(self, name = "pdf"): + def __init__(self, name="pdf"): """Initialize the generator.""" ProfileGenerator.__init__(self, name) @@ -88,7 +88,7 @@ def __init__(self, name = "pdf"): return - _parnames = ['delta1', 'delta2', 'qbroad', 'scale', 'qdamp'] + _parnames = ["delta1", "delta2", "qbroad", "scale", "qdamp"] def _setCalculator(self, calc): """Set the SrReal calulator instance. @@ -99,13 +99,11 @@ def _setCalculator(self, calc): """ self._calc = calc for pname in self.__class__._parnames: - self.addParameter( - ParameterAdapter(pname, self._calc, attr = pname) - ) + self.addParameter(ParameterAdapter(pname, self._calc, attr=pname)) self.processMetaData() return - def parallel(self, ncpu, mapfunc = None): + def parallel(self, ncpu, mapfunc=None): """Run calculation in parallel. ncpu -- Number of parallel processes. Revert to serial mode when 1. @@ -115,8 +113,9 @@ def parallel(self, ncpu, mapfunc = None): No return value. """ from diffpy.srreal.parallel import createParallelCalculator + calc_serial = self._calc - if hasattr(calc_serial, 'pqobj'): + if hasattr(calc_serial, "pqobj"): calc_serial = calc_serial.pqobj # revert to serial calculator for ncpu <= 1 if ncpu <= 1: @@ -127,6 +126,7 @@ def parallel(self, ncpu, mapfunc = None): # ncpu = min(ncpu, multiprocessing.cpu_count()) if mapfunc is None: import multiprocessing + self._pool = multiprocessing.Pool(ncpu) mapfunc = self._pool.imap_unordered @@ -157,7 +157,7 @@ def processMetaData(self): return - def setScatteringType(self, stype = "X"): + def setScatteringType(self, stype="X"): """Set the scattering type. stype -- "X" for x-ray, "N" for neutron, "E" for electrons, @@ -186,8 +186,7 @@ def getQmax(self): return self._calc.qmax def setQmin(self, qmin): - """Set the qmin value. - """ + """Set the qmin value.""" self._calc.qmin = qmin self.meta["qmin"] = self.getQmin() return @@ -196,7 +195,7 @@ def getQmin(self): """Get the qmin value.""" return self._calc.qmin - def setStructure(self, stru, name = "phase", periodic = True): + def setStructure(self, stru, name="phase", periodic=True): """Set the structure that will be used to calculate the PDF. This creates a DiffpyStructureParSet, ObjCrystCrystalParSet or @@ -222,8 +221,7 @@ def setStructure(self, stru, name = "phase", periodic = True): self.setPhase(parset, periodic) return - - def setPhase(self, parset, periodic = True): + def setPhase(self, parset, periodic=True): """Set the phase that will be used to calculate the PDF. Set the phase directly with a DiffpyStructureParSet, @@ -258,7 +256,7 @@ def _prepare(self, r): ndiv = max(len(r) - 1, 1) self._calc.rstep = (hi - lo) / ndiv self._calc.rmin = lo - self._calc.rmax = hi + 0.5*self._calc.rstep + self._calc.rmax = hi + 0.5 * self._calc.rstep return def _validate(self): @@ -298,4 +296,5 @@ def __call__(self, r): y = numpy.interp(r, rcalc, y) return y + # End class BasePDFGenerator diff --git a/src/diffpy/srfit/pdf/characteristicfunctions.py b/src/diffpy/srfit/pdf/characteristicfunctions.py index 0d38a2a6..10139dac 100644 --- a/src/diffpy/srfit/pdf/characteristicfunctions.py +++ b/src/diffpy/srfit/pdf/characteristicfunctions.py @@ -25,14 +25,22 @@ the 'registerFunction' method of that class. """ -__all__ = ["sphericalCF", "spheroidalCF", "spheroidalCF2", - "lognormalSphericalCF", "sheetCF", "shellCF", "shellCF2", "SASCF"] +__all__ = [ + "sphericalCF", + "spheroidalCF", + "spheroidalCF2", + "lognormalSphericalCF", + "sheetCF", + "shellCF", + "shellCF2", + "SASCF", +] import numpy -from numpy import pi, sqrt, log, exp, log2, ceil, sign from numpy import arctan as atan from numpy import arctanh as atanh -from numpy.fft import ifft, fftfreq +from numpy import ceil, exp, log, log2, pi, sign, sqrt +from numpy.fft import fftfreq, ifft from scipy.special import erf from diffpy.srfit.fitbase.calculator import Calculator @@ -51,11 +59,12 @@ def sphericalCF(r, psize): f = numpy.zeros(numpy.shape(r), dtype=float) if psize > 0: x = numpy.array(r, dtype=float) / psize - inside = (x < 1.0) + inside = x < 1.0 xin = x[inside] - f[inside] = 1.0 - 1.5*xin + 0.5*xin*xin*xin + f[inside] = 1.0 - 1.5 * xin + 0.5 * xin * xin * xin return f + def spheroidalCF(r, erad, prad): """Spheroidal characteristic function specified using radii. @@ -73,6 +82,7 @@ def spheroidalCF(r, erad, prad): pelpt = 1.0 * prad / erad return spheroidalCF2(r, psize, pelpt) + def spheroidalCF2(r, psize, axrat): """Spheroidal nanoparticle characteristic function. @@ -93,8 +103,8 @@ def spheroidalCF2(r, psize, axrat): # to simplify the equations v = pelpt d = 1.0 * psize - d2 = d*d - v2 = v*v + d2 = d * d + v2 = v * v if v == 1: return sphericalCF(r, psize) @@ -102,40 +112,59 @@ def spheroidalCF2(r, psize, axrat): rx = r if v < 1: - r = rx[rx <= v*psize] - r2 = r*r - f1 = 1 - 3*r/(4*d*v)*(1-r2/(4*d2)*(1+2.0/(3*v2))) \ - - 3*r/(4*d)*(1-r2/(4*d2))*v/sqrt(1-v2)*atanh(sqrt(1-v2)) - - r = rx[numpy.logical_and(rx > v*psize, rx <= psize)] - r2 = r*r - f2 = (3*d/(8*r)*(1+r2/(2*d2))*sqrt(1-r2/d2) \ - - 3*r/(4*d)*(1-r2/(4*d2))*atanh(sqrt(1-r2/d2)) \ - ) * v/sqrt(1-v2) + r = rx[rx <= v * psize] + r2 = r * r + f1 = ( + 1 + - 3 * r / (4 * d * v) * (1 - r2 / (4 * d2) * (1 + 2.0 / (3 * v2))) + - 3 * r / (4 * d) * (1 - r2 / (4 * d2)) * v / sqrt(1 - v2) * atanh(sqrt(1 - v2)) + ) + + r = rx[numpy.logical_and(rx > v * psize, rx <= psize)] + r2 = r * r + f2 = ( + ( + 3 * d / (8 * r) * (1 + r2 / (2 * d2)) * sqrt(1 - r2 / d2) + - 3 * r / (4 * d) * (1 - r2 / (4 * d2)) * atanh(sqrt(1 - r2 / d2)) + ) + * v + / sqrt(1 - v2) + ) r = rx[rx > psize] f3 = numpy.zeros_like(r) - f = numpy.concatenate((f1,f2,f3)) + f = numpy.concatenate((f1, f2, f3)) elif v > 1: r = rx[rx <= psize] - r2 = r*r - f1 = 1 - 3*r/(4*d*v)*(1-r2/(4*d2)*(1+2.0/(3*v2))) \ - - 3*r/(4*d)*(1-r2/(4*d2))*v/sqrt(v2-1)*atan(sqrt(v2-1)) - - r = rx[numpy.logical_and(rx > psize, rx <= v*psize)] - r2 = r*r - f2 = 1 - 3*r/(4*d*v)*(1-r2/(4*d2)*(1+2.0/(3*v2))) \ - - 3.0/8*(1+r2/(2*d2))*sqrt(1-d2/r2)*v/sqrt(v2-1) \ - - 3*r/(4*d)*(1-r2/(4*d2))*v/sqrt(v2-1) \ - * (atan(sqrt(v2-1)) - atan(sqrt(r2/d2-1))) - - r = rx[rx > v*psize] + r2 = r * r + f1 = ( + 1 + - 3 * r / (4 * d * v) * (1 - r2 / (4 * d2) * (1 + 2.0 / (3 * v2))) + - 3 * r / (4 * d) * (1 - r2 / (4 * d2)) * v / sqrt(v2 - 1) * atan(sqrt(v2 - 1)) + ) + + r = rx[numpy.logical_and(rx > psize, rx <= v * psize)] + r2 = r * r + f2 = ( + 1 + - 3 * r / (4 * d * v) * (1 - r2 / (4 * d2) * (1 + 2.0 / (3 * v2))) + - 3.0 / 8 * (1 + r2 / (2 * d2)) * sqrt(1 - d2 / r2) * v / sqrt(v2 - 1) + - 3 + * r + / (4 * d) + * (1 - r2 / (4 * d2)) + * v + / sqrt(v2 - 1) + * (atan(sqrt(v2 - 1)) - atan(sqrt(r2 / d2 - 1))) + ) + + r = rx[rx > v * psize] f3 = numpy.zeros_like(r) - f = numpy.concatenate((f1,f2,f3)) + f = numpy.concatenate((f1, f2, f3)) return f @@ -166,19 +195,25 @@ def lognormalSphericalCF(r, psize, psig): Source unknown """ - if psize <= 0: return numpy.zeros_like(r) - if psig <= 0: return sphericalCF(r, psize) + if psize <= 0: + return numpy.zeros_like(r) + if psig <= 0: + return sphericalCF(r, psize) - erfc = lambda x: 1.0-erf(x) + erfc = lambda x: 1.0 - erf(x) sqrt2 = sqrt(2.0) - s = sqrt(log(psig*psig/(1.0*psize*psize) + 1)) - mu = log(psize) - s*s/2; - if mu < 0: return numpy.zeros_like(r) + s = sqrt(log(psig * psig / (1.0 * psize * psize) + 1)) + mu = log(psize) - s * s / 2 + if mu < 0: + return numpy.zeros_like(r) + + return ( + 0.5 * erfc((-mu - 3 * s * s + log(r)) / (sqrt2 * s)) + + 0.25 * r * r * r * erfc((-mu + log(r)) / (sqrt2 * s)) * exp(-3 * mu - 4.5 * s * s) + - 0.75 * r * erfc((-mu - 2 * s * s + log(r)) / (sqrt2 * s)) * exp(-mu - 2.5 * s * s) + ) - return 0.5*erfc((-mu-3*s*s+log(r))/(sqrt2*s)) \ - + 0.25*r*r*r*erfc((-mu+log(r))/(sqrt2*s))*exp(-3*mu-4.5*s*s) \ - - 0.75*r*erfc((-mu-2*s*s+log(r))/(sqrt2*s))*exp(-mu-2.5*s*s) def sheetCF(r, sthick): """Nanosheet characteristic function. @@ -217,10 +252,11 @@ def shellCF(r, radius, thickness): From Lei et al., Phys. Rev. B, 80, 024118 (2009) """ - d = 1.0*thickness - a = 1.0*radius + d/2.0 + d = 1.0 * thickness + a = 1.0 * radius + d / 2.0 return shellCF2(r, a, d) + def shellCF2(r, a, delta): """Spherical shell characteristic function. @@ -232,22 +268,24 @@ def shellCF2(r, a, delta): From Lei et al., Phys. Rev. B, 80, 024118 (2009) """ - a = 1.0*a - d = 1.0*delta + a = 1.0 * a + d = 1.0 * delta a2 = a**2 d2 = d**2 - dmr = d-r + dmr = d - r dmr2 = dmr**2 - f = r * (16*a*a2 + 12*a*d*dmr + 36*a2*(2*d-r) + 3*dmr2*(2*d+r)) \ - + 2*dmr2 * (r*(2*d+r)-12*a2) * sign(dmr) \ - - 2*(2*a-r)**2 * (r*(4*a+r)-3*d2) * sign(2*a-r) \ - + r*(4*a-2*d+r)*(2*a-d-r)**2*sign(2*a-d-r) + f = ( + r * (16 * a * a2 + 12 * a * d * dmr + 36 * a2 * (2 * d - r) + 3 * dmr2 * (2 * d + r)) + + 2 * dmr2 * (r * (2 * d + r) - 12 * a2) * sign(dmr) + - 2 * (2 * a - r) ** 2 * (r * (4 * a + r) - 3 * d2) * sign(2 * a - r) + + r * (4 * a - 2 * d + r) * (2 * a - d - r) ** 2 * sign(2 * a - d - r) + ) - f[r > 2*a+d] = 0 + f[r > 2 * a + d] = 0 - den = 8.0*r*d*(12*a2+d2) - zmask = (den == 0.0) + den = 8.0 * r * d * (12 * a2 + d2) + zmask = den == 0.0 vmask = ~zmask f[vmask] /= den[vmask] f[zmask] = 1 @@ -286,6 +324,7 @@ def __init__(self, name, model): self._model = model from diffpy.srfit.sas.sasparameter import SASParameter + # Wrap normal parameters for parname in model.params: par = SASParameter(parname, model) @@ -327,11 +366,11 @@ def __call__(self, r): rmax = max(ed, 2 * r[-1]) dq = pi / rmax qmax = pi / dr - numpoints = int(2**(ceil(log2(qmax/dq)))) + numpoints = int(2 ** (ceil(log2(qmax / dq)))) qmax = dq * numpoints # Calculate F(q) = q * I(q) from model - q = fftfreq(int(qmax/dq)) * qmax + q = fftfreq(int(qmax / dq)) * qmax fq = q * self._model.evalDistribution(q) # Calculate g(r) and the effective r-points @@ -340,20 +379,20 @@ def __call__(self, r): gr = ifft(fq).imag # Calculate full-fr for normalization - assert (rp[0] == 0.0) + assert rp[0] == 0.0 frp = numpy.zeros_like(gr) frp[1:] = gr[1:] / rp[1:] # Inerpolate onto requested grid, do not use data after jump in rp - assert (numpoints % 2 == 0) + assert numpoints % 2 == 0 nhalf = numpoints / 2 fr = numpy.interp(r, rp[:nhalf], gr[:nhalf]) - vmask = (r != 0) + vmask = r != 0 fr[vmask] /= r[vmask] # Normalize. We approximate fr[0] by using the fact that f(r) is linear # at low r. By definition, fr[0] should equal 1. - fr0 = 2*frp[2] - frp[1] + fr0 = 2 * frp[2] - frp[1] fr /= fr0 # Fix potential divide-by-zero issue, fr is 1 at r == 0 diff --git a/src/diffpy/srfit/pdf/debyepdfgenerator.py b/src/diffpy/srfit/pdf/debyepdfgenerator.py index dd70d055..fcfaa577 100644 --- a/src/diffpy/srfit/pdf/debyepdfgenerator.py +++ b/src/diffpy/srfit/pdf/debyepdfgenerator.py @@ -66,7 +66,7 @@ class DebyePDFGenerator(BasePDFGenerator): """ - def setStructure(self, stru, name = "phase", periodic = False): + def setStructure(self, stru, name="phase", periodic=False): """Set the structure that will be used to calculate the PDF. This creates a DiffpyStructureParSet, ObjCrystCrystalParSet or @@ -86,8 +86,7 @@ def setStructure(self, stru, name = "phase", periodic = False): """ return BasePDFGenerator.setStructure(self, stru, name, periodic) - - def setPhase(self, parset, periodic = False): + def setPhase(self, parset, periodic=False): """Set the phase that will be used to calculate the PDF. Set the phase directly with a DiffpyStructureParSet, @@ -106,15 +105,15 @@ def setPhase(self, parset, periodic = False): """ return BasePDFGenerator.setPhase(self, parset, periodic) - - def __init__(self, name = "pdf"): - """Initialize the generator. - """ + def __init__(self, name="pdf"): + """Initialize the generator.""" from diffpy.srreal.pdfcalculator import DebyePDFCalculator + BasePDFGenerator.__init__(self, name) self._setCalculator(DebyePDFCalculator()) return + # End class DebyePDFGenerator # End of file diff --git a/src/diffpy/srfit/pdf/pdfcontribution.py b/src/diffpy/srfit/pdf/pdfcontribution.py index 1700eb5a..de485428 100644 --- a/src/diffpy/srfit/pdf/pdfcontribution.py +++ b/src/diffpy/srfit/pdf/pdfcontribution.py @@ -20,8 +20,8 @@ __all__ = ["PDFContribution"] -from diffpy.srfit.fitbase import FitContribution -from diffpy.srfit.fitbase import Profile +from diffpy.srfit.fitbase import FitContribution, Profile + class PDFContribution(FitContribution): """PDFContribution class. @@ -72,7 +72,7 @@ def __init__(self, name): self._meta = {} # Add the profile profile = Profile() - self.setProfile(profile, xname = "r") + self.setProfile(profile, xname="r") # Need a parameter for the overall scale, in the case that this is a # multi-phase fit. @@ -96,10 +96,12 @@ def loadData(self, data): """ # Get the data into a string from diffpy.srfit.util.inpututils import inputToString + datstr = inputToString(data) # Load data with a PDFParser from diffpy.srfit.pdf.pdfparser import PDFParser + parser = PDFParser() parser.parseString(datstr) @@ -107,7 +109,6 @@ def loadData(self, data): self.profile.loadParsedData(parser) return - def setCalculationRange(self, xmin=None, xmax=None, dx=None): """Set epsilon-inclusive calculation range. @@ -142,7 +143,6 @@ def setCalculationRange(self, xmin=None, xmax=None, dx=None): """ return self.profile.setCalculationRange(xmin, xmax, dx) - def savetxt(self, fname, **kwargs): """Call numpy.savetxt with x, ycalc, y, dy @@ -154,7 +154,7 @@ def savetxt(self, fname, **kwargs): # Phase methods - def addStructure(self, name, stru, periodic = True): + def addStructure(self, name, stru, periodic=True): """Add a phase that goes into the PDF calculation. name -- A name to give the generator that will manage the PDF @@ -180,9 +180,11 @@ def addStructure(self, name, stru, periodic = True): # Based on periodic, create the proper generator. if periodic: from diffpy.srfit.pdf.pdfgenerator import PDFGenerator + gen = PDFGenerator(name) else: from diffpy.srfit.pdf.debyepdfgenerator import DebyePDFGenerator + gen = DebyePDFGenerator(name) # Set up the generator @@ -191,7 +193,7 @@ def addStructure(self, name, stru, periodic = True): return gen.phase - def addPhase(self, name, parset, periodic = True): + def addPhase(self, name, parset, periodic=True): """Add a phase that goes into the PDF calculation. name -- A name to give the generator that will manage the PDF @@ -218,9 +220,11 @@ def addPhase(self, name, parset, periodic = True): # Based on periodic, create the proper generator. if periodic: from diffpy.srfit.pdf.pdfgenerator import PDFGenerator + gen = PDFGenerator(name) else: from diffpy.srfit.pdf.debyepdfgenerator import DebyePDFGenerator + gen = DebyePDFGenerator(name) # Set up the generator @@ -268,8 +272,7 @@ def _getMetaValue(self, kwd): val = self.profile.meta.get(kwd) return val - - def setScatteringType(self, type = "X"): + def setScatteringType(self, type="X"): """Set the scattering type. type -- "X" for x-ray or "N" for neutron @@ -298,8 +301,7 @@ def getQmax(self): return self._getMetaValue("qmax") def setQmin(self, qmin): - """Set the qmin value. - """ + """Set the qmin value.""" self._meta["qmin"] = qmin for gen in self._generators.values(): gen.setQmin(qmin) @@ -309,4 +311,5 @@ def getQmin(self): """Get the qmin value.""" return self._getMetaValue("qmin") + # End of file diff --git a/src/diffpy/srfit/pdf/pdfgenerator.py b/src/diffpy/srfit/pdf/pdfgenerator.py index 5a118ceb..d7ae7851 100644 --- a/src/diffpy/srfit/pdf/pdfgenerator.py +++ b/src/diffpy/srfit/pdf/pdfgenerator.py @@ -66,12 +66,13 @@ class PDFGenerator(BasePDFGenerator): """ - def __init__(self, name = "pdf"): - """Initialize the generator. - """ + def __init__(self, name="pdf"): + """Initialize the generator.""" from diffpy.srreal.pdfcalculator import PDFCalculator + BasePDFGenerator.__init__(self, name) self._setCalculator(PDFCalculator()) return + # End class PDFGenerator diff --git a/src/diffpy/srfit/pdf/pdfparser.py b/src/diffpy/srfit/pdf/pdfparser.py index 945c5184..84d9d060 100644 --- a/src/diffpy/srfit/pdf/pdfparser.py +++ b/src/diffpy/srfit/pdf/pdfparser.py @@ -23,11 +23,13 @@ __all__ = ["PDFParser"] import re + import numpy from diffpy.srfit.exceptions import ParseError from diffpy.srfit.fitbase.profileparser import ProfileParser + class PDFParser(ProfileParser): """Class for holding a diffraction pattern. @@ -91,15 +93,15 @@ def parseString(self, patstring): """ # useful regex patterns: - rx = { 'f' : r'[-+]?(\d+(\.\d*)?|\d*\.\d+)([eE][-+]?\d+)?' } + rx = {"f": r"[-+]?(\d+(\.\d*)?|\d*\.\d+)([eE][-+]?\d+)?"} # find where does the data start - res = re.search(r'^#+ start data\s*(?:#.*\s+)*', patstring, re.M) + res = re.search(r"^#+ start data\s*(?:#.*\s+)*", patstring, re.M) # start_data is position where the first data line starts if res: start_data = res.end() else: # find line that starts with a floating point number - regexp = r'^\s*%(f)s' % rx + regexp = r"^\s*%(f)s" % rx res = re.search(regexp, patstring, re.M) if res: start_data = res.start() @@ -109,19 +111,19 @@ def parseString(self, patstring): databody = patstring[start_data:].strip() # find where the metadata starts - metadata = '' - res = re.search(r'^#+\ +metadata\b\n', header, re.M) + metadata = "" + res = re.search(r"^#+\ +metadata\b\n", header, re.M) if res: - metadata = header[res.end():] - header = header[:res.start()] + metadata = header[res.end() :] + header = header[: res.start()] # parse header meta = self._meta # stype - if re.search('(x-?ray|PDFgetX)', header, re.I): - meta["stype"] = 'X' - elif re.search('(neutron|PDFgetN)', header, re.I): - meta["stype"] = 'N' + if re.search("(x-?ray|PDFgetX)", header, re.I): + meta["stype"] = "X" + elif re.search("(neutron|PDFgetN)", header, re.I): + meta["stype"] = "N" # qmin regexp = r"\bqmin *= *(%(f)s)\b" % rx res = re.search(regexp, header, re.I) @@ -156,12 +158,12 @@ def parseString(self, patstring): regexp = r"\b(?:temp|temperature|T)\ *=\ *(%(f)s)\b" % rx res = re.search(regexp, header) if res: - meta['temperature'] = float(res.groups()[0]) + meta["temperature"] = float(res.groups()[0]) # doping regexp = r"\b(?:x|doping)\ *=\ *(%(f)s)\b" % rx res = re.search(regexp, header) if res: - meta['doping'] = float(res.groups()[0]) + meta["doping"] = float(res.groups()[0]) # parsing gerneral metadata if metadata: @@ -170,12 +172,12 @@ def parseString(self, patstring): res = re.search(regexp, metadata, re.M) if res: meta[res.groups()[0]] = float(res.groups()[1]) - metadata = metadata[res.end():] + metadata = metadata[res.end() :] else: break # read actual data - robs, Gobs, drobs, dGobs - inf_or_nan = re.compile('(?i)^[+-]?(NaN|Inf)\\b') + inf_or_nan = re.compile("(?i)^[+-]?(NaN|Inf)\\b") has_drobs = True has_dGobs = True # raise ParseError if something goes wrong @@ -190,15 +192,13 @@ def parseString(self, patstring): robs.append(float(v[0])) Gobs.append(float(v[1])) # drobs is valid if all values are defined and positive - has_drobs = (has_drobs and - len(v) > 2 and not inf_or_nan.match(v[2])) + has_drobs = has_drobs and len(v) > 2 and not inf_or_nan.match(v[2]) if has_drobs: v2 = float(v[2]) has_drobs = v2 > 0.0 drobs.append(v2) # dGobs is valid if all values are defined and positive - has_dGobs = (has_dGobs and - len(v) > 3 and not inf_or_nan.match(v[3])) + has_dGobs = has_dGobs and len(v) > 3 and not inf_or_nan.match(v[3]) if has_dGobs: v3 = float(v[3]) has_dGobs = v3 > 0.0 @@ -220,4 +220,5 @@ def parseString(self, patstring): self._banks.append([robs, Gobs, drobs, dGobs]) return + # End of PDFParser diff --git a/src/diffpy/srfit/sas/__init__.py b/src/diffpy/srfit/sas/__init__.py index c454a86e..d414207d 100644 --- a/src/diffpy/srfit/sas/__init__.py +++ b/src/diffpy/srfit/sas/__init__.py @@ -16,12 +16,11 @@ """SAS calculation tools. """ -__all__ = ["SASGenerator", "SASParser", "SASProfile", "PrCalculator", - "CFCalculator"] +__all__ = ["SASGenerator", "SASParser", "SASProfile", "PrCalculator", "CFCalculator"] +from .prcalculator import CFCalculator, PrCalculator from .sasgenerator import SASGenerator from .sasparser import SASParser from .sasprofile import SASProfile -from .prcalculator import PrCalculator, CFCalculator # End of file diff --git a/src/diffpy/srfit/sas/prcalculator.py b/src/diffpy/srfit/sas/prcalculator.py index 0ce1ad41..edb1da18 100644 --- a/src/diffpy/srfit/sas/prcalculator.py +++ b/src/diffpy/srfit/sas/prcalculator.py @@ -67,7 +67,8 @@ def __init__(self, name): global Invertor if Invertor is None: from diffpy.srfit.sas.sasimport import sasimport - Invertor = sasimport('sas.pr.invertor').Invertor + + Invertor = sasimport("sas.pr.invertor").Invertor self._invertor = Invertor() @@ -97,8 +98,10 @@ def __call__(self, r): pr = numpy.array(pr) return self.scale.value * pr + # End class PrCalculator + class CFCalculator(PrCalculator): """A class for calculating the characteristic function (CF) from data. @@ -130,4 +133,5 @@ def __call__(self, r): fr[0] = 1 return fr + # End class CFCalculator diff --git a/src/diffpy/srfit/sas/sasgenerator.py b/src/diffpy/srfit/sas/sasgenerator.py index 74a60594..dbf3f4a1 100644 --- a/src/diffpy/srfit/sas/sasgenerator.py +++ b/src/diffpy/srfit/sas/sasgenerator.py @@ -69,4 +69,5 @@ def __call__(self, q): """Calculate I(Q) for the BaseModel.""" return self._model.evalDistribution(q) + # End class SASGenerator diff --git a/src/diffpy/srfit/sas/sasimport.py b/src/diffpy/srfit/sas/sasimport.py index ba39fb4a..e3e15100 100644 --- a/src/diffpy/srfit/sas/sasimport.py +++ b/src/diffpy/srfit/sas/sasimport.py @@ -17,6 +17,7 @@ Universal import functions for volatile SasView/SansViews API-s. """ + def sasimport(modname): """Import specified module from the SasView sas package. @@ -25,41 +26,44 @@ def sasimport(modname): When specified import does not work directly, try older API-s and raise DeprecationWarning. Raise ImportError if nothing works. """ - if not modname.startswith('sas.'): + if not modname.startswith("sas."): emsg = 'Module name must start with "sas."' raise ValueError(emsg) mobj = None # standard import try: - exec('import %s as mobj' % modname) + exec("import %s as mobj" % modname) except ImportError: pass else: return mobj # revert to the old sans namespace, sas --> sans - modsans = 'sans' + modname[3:] + modsans = "sans" + modname[3:] import warnings - wfmt = ("Using obsolete package %r instead of %r. Please install " - "SasView 3.1 or the srfit-sasview package from Anaconda.") + + wfmt = ( + "Using obsolete package %r instead of %r. Please install " + "SasView 3.1 or the srfit-sasview package from Anaconda." + ) wmsg = wfmt % (modsans, modname) try: - exec('import %s as mobj' % modsans) + exec("import %s as mobj" % modsans) warnings.warn(wmsg, DeprecationWarning) except ImportError: pass else: return mobj # finally check the oldest DataLoader API for sas.dataloader - if modname.startswith('sas.dataloader'): - modloader = 'DataLoader' + modname[14:] + if modname.startswith("sas.dataloader"): + modloader = "DataLoader" + modname[14:] wmsg = wfmt % (modloader, modname) try: - exec('import %s as mobj' % modloader) + exec("import %s as mobj" % modloader) warnings.warn(wmsg, DeprecationWarning) except ImportError: pass else: return mobj # Obsolete API-s failed here. Import again and let it raise ImportError. - exec('import %s as mobj' % modname) + exec("import %s as mobj" % modname) raise AssertionError("The import above was supposed to fail.") diff --git a/src/diffpy/srfit/sas/sasparameter.py b/src/diffpy/srfit/sas/sasparameter.py index 7f3886d4..fbf841aa 100644 --- a/src/diffpy/srfit/sas/sasparameter.py +++ b/src/diffpy/srfit/sas/sasparameter.py @@ -43,7 +43,7 @@ class SASParameter(Parameter): """ - def __init__(self, name, model, parname = None): + def __init__(self, name, model, parname=None): """Create the Parameter. name -- Name of the Parameter @@ -60,7 +60,7 @@ def __init__(self, name, model, parname = None): def getValue(self): """Get the value of the Parameter.""" - value = self._model.getParam(self._parname) + value = self._model.getParam(self._parname) return value def setValue(self, value): @@ -70,4 +70,5 @@ def setValue(self, value): self.notify() return self + # End of class SASParameter diff --git a/src/diffpy/srfit/sas/sasparser.py b/src/diffpy/srfit/sas/sasparser.py index 3177954a..bf3cec74 100644 --- a/src/diffpy/srfit/sas/sasparser.py +++ b/src/diffpy/srfit/sas/sasparser.py @@ -83,7 +83,7 @@ def parseFile(self, filename): """ - Loader = sasimport('sas.dataloader.loader').Loader + Loader = sasimport("sas.dataloader.loader").Loader loader = Loader() try: @@ -117,8 +117,9 @@ def parseString(self, patstring): """ # This calls on parseFile, as that is how the sas data loader works. import tempfile + fh, fn = tempfile.mkstemp() - outfile = open(fn, 'w') + outfile = open(fn, "w") fn.write(patstring) outfile.close() self.parseFile(fn) @@ -127,6 +128,7 @@ def parseString(self, patstring): # Close the temporary file and delete it import os + os.close(fh) os.remove(fn) return diff --git a/src/diffpy/srfit/sas/sasprofile.py b/src/diffpy/srfit/sas/sasprofile.py index ef0bff3c..e35adfb1 100644 --- a/src/diffpy/srfit/sas/sasprofile.py +++ b/src/diffpy/srfit/sas/sasprofile.py @@ -75,7 +75,7 @@ def __init__(self, datainfo): self._dyobs = self._datainfo.dy return - def setObservedProfile(self, xobs, yobs, dyobs = None): + def setObservedProfile(self, xobs, yobs, dyobs=None): """Set the observed profile. This is overloaded to change the value within the datainfo object. diff --git a/src/diffpy/srfit/structure/__init__.py b/src/diffpy/srfit/structure/__init__.py index 54618c4c..5904f06f 100644 --- a/src/diffpy/srfit/structure/__init__.py +++ b/src/diffpy/srfit/structure/__init__.py @@ -32,18 +32,22 @@ def struToParameterSet(name, stru): """ from diffpy.srfit.structure.diffpyparset import DiffpyStructureParSet + if DiffpyStructureParSet.canAdapt(stru): return DiffpyStructureParSet(name, stru) from diffpy.srfit.structure.objcrystparset import ObjCrystCrystalParSet + if ObjCrystCrystalParSet.canAdapt(stru): return ObjCrystCrystalParSet(name, stru) from diffpy.srfit.structure.objcrystparset import ObjCrystMoleculeParSet + if ObjCrystMoleculeParSet.canAdapt(stru): return ObjCrystMoleculeParSet(name, stru) from diffpy.srfit.structure.cctbxparset import CCTBXCrystalParSet + if CCTBXCrystalParSet.canAdapt(stru): return CCTBXCrystalParSet(name, stru) diff --git a/src/diffpy/srfit/structure/bvsrestraint.py b/src/diffpy/srfit/structure/bvsrestraint.py index 38a5ea7a..43d9a6ba 100644 --- a/src/diffpy/srfit/structure/bvsrestraint.py +++ b/src/diffpy/srfit/structure/bvsrestraint.py @@ -21,8 +21,8 @@ __all__ = ["BVSRestraint"] -from diffpy.srfit.fitbase.restraint import Restraint from diffpy.srfit.exceptions import SrFitError +from diffpy.srfit.fitbase.restraint import Restraint class BVSRestraint(Restraint): @@ -41,7 +41,7 @@ class BVSRestraint(Restraint): """ - def __init__(self, parset, sig = 1, scaled = False): + def __init__(self, parset, sig=1, scaled=False): """Initialize the Restraint. parset -- SrRealParSet that creates this BVSRestraint. @@ -52,13 +52,14 @@ def __init__(self, parset, sig = 1, scaled = False): """ from diffpy.srreal.bvscalculator import BVSCalculator + self._calc = BVSCalculator() self._parset = parset self.sig = float(sig) self.scaled = bool(scaled) return - def penalty(self, w = 1.0): + def penalty(self, w=1.0): """Calculate the penalty of the restraint. w -- The point-average chi^2 which is optionally used to scale the @@ -74,7 +75,8 @@ def penalty(self, w = 1.0): penalty /= self.sig**2 # Optionally scale by w - if self.scaled: penalty *= w + if self.scaled: + penalty *= w return penalty @@ -85,16 +87,20 @@ def _validate(self): """ from numpy import nan + p = self.penalty() if p is None or p is nan: raise SrFitError("Cannot evaluate penalty") v = self._calc.value if len(v) > 1 and not v.any(): - emsg = ("Bond valence sums are all zero. Check atom symbols in " - "the structure or define custom bond-valence parameters.") + emsg = ( + "Bond valence sums are all zero. Check atom symbols in " + "the structure or define custom bond-valence parameters." + ) raise SrFitError(emsg) return # End of class BVSRestraint + # End of file diff --git a/src/diffpy/srfit/structure/cctbxparset.py b/src/diffpy/srfit/structure/cctbxparset.py index f3b04d8b..28f24bd1 100644 --- a/src/diffpy/srfit/structure/cctbxparset.py +++ b/src/diffpy/srfit/structure/cctbxparset.py @@ -32,8 +32,7 @@ from diffpy.srfit.fitbase.parameterset import ParameterSet from diffpy.srfit.structure.basestructureparset import BaseStructureParSet -__all__ = ["CCTBXScattererParSet", "CCTBXUnitCellParSet", - "CCTBXCrystalParSet"] +__all__ = ["CCTBXScattererParSet", "CCTBXUnitCellParSet", "CCTBXCrystalParSet"] class CCTBXScattererParSet(ParameterSet): @@ -65,16 +64,11 @@ def __init__(self, name, strups, idx): self.idx = idx # x, y, z, occupancy - self.addParameter(ParameterAdapter("x", None, self._xyzgetter(0), - self._xyzsetter(0))) - self.addParameter(ParameterAdapter("y", None, self._xyzgetter(1), - self._xyzsetter(1))) - self.addParameter(ParameterAdapter("z", None, self._xyzgetter(2), - self._xyzsetter(2))) - self.addParameter(ParameterAdapter("occupancy", None, self._getocc, - self._setocc)) - self.addParameter(ParameterAdapter("Uiso", None, self._getuiso, - self._setuiso)) + self.addParameter(ParameterAdapter("x", None, self._xyzgetter(0), self._xyzsetter(0))) + self.addParameter(ParameterAdapter("y", None, self._xyzgetter(1), self._xyzsetter(1))) + self.addParameter(ParameterAdapter("z", None, self._xyzgetter(2), self._xyzsetter(2))) + self.addParameter(ParameterAdapter("occupancy", None, self._getocc, self._setocc)) + self.addParameter(ParameterAdapter("Uiso", None, self._getuiso, self._setuiso)) return # Getters and setters @@ -115,8 +109,10 @@ def _getElem(self): element = property(_getElem) + # End class CCTBXScattererParSet + class CCTBXUnitCellParSet(ParameterSet): """A wrapper for cctbx unit_cell object. @@ -137,18 +133,12 @@ def __init__(self, strups): self.strups = strups self._latpars = list(self.strups.stru.unit_cell().parameters()) - self.addParameter(ParameterAdapter("a", None, self._latgetter(0), - self._latsetter(0))) - self.addParameter(ParameterAdapter("b", None, self._latgetter(1), - self._latsetter(1))) - self.addParameter(ParameterAdapter("c", None, self._latgetter(2), - self._latsetter(2))) - self.addParameter(ParameterAdapter("alpha", None, self._latgetter(3), - self._latsetter(3))) - self.addParameter(ParameterAdapter("beta", None, self._latgetter(4), - self._latsetter(4))) - self.addParameter(ParameterAdapter("gamma", None, self._latgetter(5), - self._latsetter(5))) + self.addParameter(ParameterAdapter("a", None, self._latgetter(0), self._latsetter(0))) + self.addParameter(ParameterAdapter("b", None, self._latgetter(1), self._latsetter(1))) + self.addParameter(ParameterAdapter("c", None, self._latgetter(2), self._latsetter(2))) + self.addParameter(ParameterAdapter("alpha", None, self._latgetter(3), self._latsetter(3))) + self.addParameter(ParameterAdapter("beta", None, self._latgetter(4), self._latsetter(4))) + self.addParameter(ParameterAdapter("gamma", None, self._latgetter(5), self._latsetter(5))) return @@ -173,6 +163,7 @@ def f(dummy, value): # FIXME - Special positions should be constant. + class CCTBXCrystalParSet(BaseStructureParSet): """A wrapper for CCTBX structure. @@ -201,14 +192,15 @@ def __init__(self, name, stru): for s in stru.scatterers(): el = s.element_symbol() i = cdict.get(el, 0) - sname = "%s%i"%(el,i) - cdict[el] = i+1 + sname = "%s%i" % (el, i) + cdict[el] = i + 1 scatterer = CCTBXScattererParSet(sname, self, i) self.addParameterSet(scatterer) self.scatterers.append(scatterer) # Constrain the lattice from diffpy.srfit.structure.sgconstraints import _constrainSpaceGroup + symbol = self.getSpaceGroup() _constrainSpaceGroup(self, symbol) @@ -231,16 +223,11 @@ def update(self): # Create the symmetry object from cctbx.crystal import symmetry - symm = symmetry( - unit_cell = self.unitcell._latpars, - space_group_symbol = sgn - ) + + symm = symmetry(unit_cell=self.unitcell._latpars, space_group_symbol=sgn) # Now the new structure - newstru = stru.__class__( - crystal_symmetry = symm, - scatterers = stru.scatterers() - ) + newstru = stru.__class__(crystal_symmetry=symm, scatterers=stru.scatterers()) self.unitcell._latpars = list(newstru.unit_cell().parameters()) @@ -278,5 +265,4 @@ def getSpaceGroup(self): return t.lookup_symbol() - # End class CCTBXCrystalParSet diff --git a/src/diffpy/srfit/structure/diffpyparset.py b/src/diffpy/srfit/structure/diffpyparset.py index 4278bf13..bd8d6de4 100644 --- a/src/diffpy/srfit/structure/diffpyparset.py +++ b/src/diffpy/srfit/structure/diffpyparset.py @@ -30,8 +30,7 @@ __all__ = ["DiffpyStructureParSet"] -from diffpy.srfit.fitbase.parameter import ParameterProxy -from diffpy.srfit.fitbase.parameter import ParameterAdapter +from diffpy.srfit.fitbase.parameter import ParameterAdapter, ParameterProxy from diffpy.srfit.fitbase.parameterset import ParameterSet from diffpy.srfit.structure.srrealparset import SrRealParSet from diffpy.srfit.util.argbinders import bind2nd @@ -94,24 +93,21 @@ def __init__(self, name, atom): self.atom = atom a = atom # x, y, z, occupancy - self.addParameter(ParameterAdapter("x", a, _xyzgetter(0), - _xyzsetter(0))) - self.addParameter(ParameterAdapter("y", a, _xyzgetter(1), - _xyzsetter(1))) - self.addParameter(ParameterAdapter("z", a, _xyzgetter(2), - _xyzsetter(2))) - occupancy = ParameterAdapter("occupancy", a, attr = "occupancy") + self.addParameter(ParameterAdapter("x", a, _xyzgetter(0), _xyzsetter(0))) + self.addParameter(ParameterAdapter("y", a, _xyzgetter(1), _xyzsetter(1))) + self.addParameter(ParameterAdapter("z", a, _xyzgetter(2), _xyzsetter(2))) + occupancy = ParameterAdapter("occupancy", a, attr="occupancy") self.addParameter(occupancy) self.addParameter(ParameterProxy("occ", occupancy)) # U - self.addParameter(ParameterAdapter("U11", a, attr = "U11")) - self.addParameter(ParameterAdapter("U22", a, attr = "U22")) - self.addParameter(ParameterAdapter("U33", a, attr = "U33")) - U12 = ParameterAdapter("U12", a, attr = "U12") + self.addParameter(ParameterAdapter("U11", a, attr="U11")) + self.addParameter(ParameterAdapter("U22", a, attr="U22")) + self.addParameter(ParameterAdapter("U33", a, attr="U33")) + U12 = ParameterAdapter("U12", a, attr="U12") U21 = ParameterProxy("U21", U12) - U13 = ParameterAdapter("U13", a, attr = "U13") + U13 = ParameterAdapter("U13", a, attr="U13") U31 = ParameterProxy("U31", U13) - U23 = ParameterAdapter("U23", a, attr = "U23") + U23 = ParameterAdapter("U23", a, attr="U23") U32 = ParameterProxy("U32", U23) self.addParameter(U12) self.addParameter(U21) @@ -119,16 +115,16 @@ def __init__(self, name, atom): self.addParameter(U31) self.addParameter(U23) self.addParameter(U32) - self.addParameter(ParameterAdapter("Uiso", a, attr = "Uisoequiv")) + self.addParameter(ParameterAdapter("Uiso", a, attr="Uisoequiv")) # B - self.addParameter(ParameterAdapter("B11", a, attr = "B11")) - self.addParameter(ParameterAdapter("B22", a, attr = "B22")) - self.addParameter(ParameterAdapter("B33", a, attr = "B33")) - B12 = ParameterAdapter("B12", a, attr = "B12") + self.addParameter(ParameterAdapter("B11", a, attr="B11")) + self.addParameter(ParameterAdapter("B22", a, attr="B22")) + self.addParameter(ParameterAdapter("B33", a, attr="B33")) + B12 = ParameterAdapter("B12", a, attr="B12") B21 = ParameterProxy("B21", B12) - B13 = ParameterAdapter("B13", a, attr = "B13") + B13 = ParameterAdapter("B13", a, attr="B13") B31 = ParameterProxy("B31", B13) - B23 = ParameterAdapter("B23", a, attr = "B23") + B23 = ParameterAdapter("B23", a, attr="B23") B32 = ParameterProxy("B32", B23) self.addParameter(B12) self.addParameter(B21) @@ -136,7 +132,7 @@ def __init__(self, name, atom): self.addParameter(B31) self.addParameter(B23) self.addParameter(B32) - self.addParameter(ParameterAdapter("Biso", a, attr = "Bisoequiv")) + self.addParameter(ParameterAdapter("Biso", a, attr="Bisoequiv")) return def __repr__(self): @@ -150,12 +146,14 @@ def _setElem(self, el): element = property(_getElem, _setElem, "type of atom") + # End class DiffpyAtomParSet def _latgetter(par): return bind2nd(getattr, par) + def _latsetter(par): return bind2nd(setattr, par) @@ -186,23 +184,18 @@ def __init__(self, lattice): self.angunits = "deg" self.lattice = lattice l = lattice - self.addParameter(ParameterAdapter("a", l, _latgetter("a"), - _latsetter("a"))) - self.addParameter(ParameterAdapter("b", l, _latgetter("b"), - _latsetter("b"))) - self.addParameter(ParameterAdapter("c", l, _latgetter("c"), - _latsetter("c"))) - self.addParameter(ParameterAdapter("alpha", l, _latgetter("alpha"), - _latsetter("alpha"))) - self.addParameter(ParameterAdapter("beta", l, _latgetter("beta"), - _latsetter("beta"))) - self.addParameter(ParameterAdapter("gamma", l, _latgetter("gamma"), - _latsetter("gamma"))) + self.addParameter(ParameterAdapter("a", l, _latgetter("a"), _latsetter("a"))) + self.addParameter(ParameterAdapter("b", l, _latgetter("b"), _latsetter("b"))) + self.addParameter(ParameterAdapter("c", l, _latgetter("c"), _latsetter("c"))) + self.addParameter(ParameterAdapter("alpha", l, _latgetter("alpha"), _latsetter("alpha"))) + self.addParameter(ParameterAdapter("beta", l, _latgetter("beta"), _latsetter("beta"))) + self.addParameter(ParameterAdapter("gamma", l, _latgetter("gamma"), _latsetter("gamma"))) return def __repr__(self): return repr(self.lattice) + # End class DiffpyLatticeParSet @@ -242,11 +235,11 @@ def __init__(self, name, stru): for a in stru: el = a.element.title() # Try to sanitize the name. - el = el.replace("+","p") - el = el.replace("-","m") + el = el.replace("+", "p") + el = el.replace("-", "m") i = cdict.get(el, 0) - aname = "%s%i"%(el,i) - cdict[el] = i+1 + aname = "%s%i" % (el, i) + cdict[el] = i + 1 atom = DiffpyAtomParSet(aname, a) self.addParameterSet(atom) self.atoms.append(atom) @@ -264,6 +257,7 @@ def getLattice(self): def canAdapt(self, stru): """Return whether the structure can be adapted by this class.""" from diffpy.structure import Structure + return isinstance(stru, Structure) def getScatterers(self): @@ -286,7 +280,9 @@ def _getSrRealStructure(self): """ from diffpy.srreal.structureadapter import nometa + stru = SrRealParSet._getSrRealStructure(self) return nometa(stru) + # End class DiffpyStructureParSet diff --git a/src/diffpy/srfit/structure/objcrystparset.py b/src/diffpy/srfit/structure/objcrystparset.py index ac4f3b43..3a8d2045 100644 --- a/src/diffpy/srfit/structure/objcrystparset.py +++ b/src/diffpy/srfit/structure/objcrystparset.py @@ -40,13 +40,16 @@ __all__ = ["ObjCrystMoleculeParSet", "ObjCrystCrystalParSet"] import numpy - -from pyobjcryst.molecule import GetBondLength, GetBondAngle, GetDihedralAngle -from pyobjcryst.molecule import StretchModeBondLength, StretchModeBondAngle -from pyobjcryst.molecule import StretchModeTorsion - -from diffpy.srfit.fitbase.parameter import Parameter, ParameterAdapter -from diffpy.srfit.fitbase.parameter import ParameterProxy +from pyobjcryst.molecule import ( + GetBondAngle, + GetBondLength, + GetDihedralAngle, + StretchModeBondAngle, + StretchModeBondLength, + StretchModeTorsion, +) + +from diffpy.srfit.fitbase.parameter import Parameter, ParameterAdapter, ParameterProxy from diffpy.srfit.fitbase.parameterset import ParameterSet from diffpy.srfit.structure.srrealparset import SrRealParSet @@ -83,11 +86,10 @@ def __init__(self, name, scat, parent): self.parent = parent # x, y, z, occ - self.addParameter(ParameterAdapter("x", self.scat, attr = "X")) - self.addParameter(ParameterAdapter("y", self.scat, attr = "Y")) - self.addParameter(ParameterAdapter("z", self.scat, attr = "Z")) - self.addParameter(ParameterAdapter("occ", self.scat, attr = - "Occupancy")) + self.addParameter(ParameterAdapter("x", self.scat, attr="X")) + self.addParameter(ParameterAdapter("y", self.scat, attr="Y")) + self.addParameter(ParameterAdapter("z", self.scat, attr="Z")) + self.addParameter(ParameterAdapter("occ", self.scat, attr="Occupancy")) return def isDummy(self): @@ -101,6 +103,7 @@ def hasScatterers(self): # End class ObjCrystScattererParSet + class ObjCrystAtomParSet(ObjCrystScattererParSet): """A adaptor for a pyobjcryst.Atom. @@ -135,15 +138,15 @@ def __init__(self, name, atom, parent): sp = atom.GetScatteringPower() # The B-parameters - self.addParameter(ParameterAdapter("Biso", sp, attr = "Biso")) - self.addParameter(ParameterAdapter("B11", sp, attr = "B11")) - self.addParameter(ParameterAdapter("B22", sp, attr = "B22")) - self.addParameter(ParameterAdapter("B33", sp, attr = "B33")) - B12 = ParameterAdapter("B12", sp, attr = "B12") + self.addParameter(ParameterAdapter("Biso", sp, attr="Biso")) + self.addParameter(ParameterAdapter("B11", sp, attr="B11")) + self.addParameter(ParameterAdapter("B22", sp, attr="B22")) + self.addParameter(ParameterAdapter("B33", sp, attr="B33")) + B12 = ParameterAdapter("B12", sp, attr="B12") B21 = ParameterProxy("B21", B12) - B13 = ParameterAdapter("B13", sp, attr = "B13") + B13 = ParameterAdapter("B13", sp, attr="B13") B31 = ParameterProxy("B31", B13) - B23 = ParameterAdapter("B23", sp, attr = "B23") + B23 = ParameterAdapter("B23", sp, attr="B23") B32 = ParameterProxy("B32", B23) self.addParameter(B12) self.addParameter(B21) @@ -163,8 +166,10 @@ def _getElem(self): element = property(_getElem) + # End class ObjCrystAtomParSet + class ObjCrystMoleculeParSet(ObjCrystScattererParSet): """A adaptor for a pyobjcryst.Molecule. @@ -188,7 +193,7 @@ class ObjCrystMoleculeParSet(ObjCrystScattererParSet): """ - def __init__(self, name, molecule, parent = None): + def __init__(self, name, molecule, parent=None): """Initialize name -- The name of the scatterer @@ -200,10 +205,10 @@ def __init__(self, name, molecule, parent = None): self.stru = molecule # Add orientiation quaternion - self.addParameter(ParameterAdapter("q0", self.scat, attr = "Q0")) - self.addParameter(ParameterAdapter("q1", self.scat, attr = "Q1")) - self.addParameter(ParameterAdapter("q2", self.scat, attr = "Q2")) - self.addParameter(ParameterAdapter("q3", self.scat, attr = "Q3")) + self.addParameter(ParameterAdapter("q0", self.scat, attr="Q0")) + self.addParameter(ParameterAdapter("q1", self.scat, attr="Q1")) + self.addParameter(ParameterAdapter("q2", self.scat, attr="Q2")) + self.addParameter(ParameterAdapter("q3", self.scat, attr="Q3")) # Wrap the MolAtoms within the molecule self.atoms = [] @@ -215,7 +220,7 @@ def __init__(self, name, molecule, parent = None): if not name: raise AttributeError("Each MolAtom must have a name") if name in anames: - raise AttributeError("MolAtom name '%s' is duplicated"%name) + raise AttributeError("MolAtom name '%s' is duplicated" % name) atom = ObjCrystMolAtomParSet(name, a, self) atom.molecule = self @@ -229,10 +234,11 @@ def __init__(self, name, molecule, parent = None): def canAdapt(self, stru): """Return whether the structure can be adapted by this class.""" from pyobjcryst.molecule import Molecule + return isinstance(stru, Molecule) # Part of SrRealParSet interface - def useSymmetry(self, use = True): + def useSymmetry(self, use=True): """Set this structure to use symmetry. This structure object does not support symmetry. @@ -327,18 +333,17 @@ def wrapStretchModeParameters(self): atom1 = getattr(self, name1) atom2 = getattr(self, name2) - par = ObjCrystBondLengthParameter(name, atom1, atom2, mode = mode) + par = ObjCrystBondLengthParameter(name, atom1, atom2, mode=mode) atoms = [] for a in mode.GetAtoms(): name = a.GetName() - atoms.append( getattr(self, name) ) + atoms.append(getattr(self, name)) par.AddAtoms(atoms) self.addParameter(par) - for mode in self.scat.GetStretchModeBondAngleList(): name1 = mode.mpAtom0.GetName() name2 = mode.mpAtom1.GetName() @@ -350,21 +355,19 @@ def wrapStretchModeParameters(self): atom2 = getattr(self, name2) atom3 = getattr(self, name3) - par = ObjCrystBondAngleParameter(name, atom1, atom2, atom3, mode = - mode) + par = ObjCrystBondAngleParameter(name, atom1, atom2, atom3, mode=mode) atoms = [] for a in mode.GetAtoms(): name = a.GetName() - atoms.append( getattr(self, name) ) + atoms.append(getattr(self, name)) par.AddAtoms(atoms) self.addParameter(par) return - def restrainBondLength(self, atom1, atom2, length, sigma, delta, scaled = - False): + def restrainBondLength(self, atom1, atom2, length, sigma, delta, scaled=False): """Add a bond length restraint. This creates an instance of ObjCrystBondLengthRestraint and adds it to @@ -388,8 +391,7 @@ def restrainBondLength(self, atom1, atom2, length, sigma, delta, scaled = return res - def restrainBondLengthParameter(self, par, length, sigma, delta, scaled = - False): + def restrainBondLengthParameter(self, par, length, sigma, delta, scaled=False): """Add a bond length restraint. This creates an instance of ObjCrystBondLengthRestraint and adds it to @@ -407,11 +409,9 @@ def restrainBondLengthParameter(self, par, length, sigma, delta, scaled = 'unrestrain' method. """ - return self.restrainBondLength(par.atom1, par.atom2, length, sigma, - delta, scaled) + return self.restrainBondLength(par.atom1, par.atom2, length, sigma, delta, scaled) - def restrainBondAngle(self, atom1, atom2, atom3, angle, sigma, delta, - scaled = False): + def restrainBondAngle(self, atom1, atom2, atom3, angle, sigma, delta, scaled=False): """Add a bond angle restraint. This creates an instance of ObjCrystBondAngleRestraint and adds it to @@ -432,14 +432,12 @@ def restrainBondAngle(self, atom1, atom2, atom3, angle, sigma, delta, 'unrestrain' method. """ - res = ObjCrystBondAngleRestraint(atom1, atom2, atom3, angle, sigma, - delta, scaled) + res = ObjCrystBondAngleRestraint(atom1, atom2, atom3, angle, sigma, delta, scaled) self._restraints.add(res) return res - def restrainBondAngleParameter(self, par, angle, sigma, delta, - scaled = False): + def restrainBondAngleParameter(self, par, angle, sigma, delta, scaled=False): """Add a bond angle restraint. This creates an instance of ObjCrystBondAngleRestraint and adds it to @@ -457,11 +455,9 @@ def restrainBondAngleParameter(self, par, angle, sigma, delta, 'unrestrain' method. """ - return self.restrainBondAngle(par.atom1, par.atom2, par.atom3, angle, - sigma, delta, scaled) + return self.restrainBondAngle(par.atom1, par.atom2, par.atom3, angle, sigma, delta, scaled) - def restrainDihedralAngle(self, atom1, atom2, atom3, atom4, angle, sigma, - delta, scaled = False): + def restrainDihedralAngle(self, atom1, atom2, atom3, atom4, angle, sigma, delta, scaled=False): """Add a dihedral angle restraint. This creates an instance of ObjCrystDihedralAngleRestraint and adds it @@ -482,14 +478,12 @@ def restrainDihedralAngle(self, atom1, atom2, atom3, atom4, angle, sigma, 'unrestrain' method. """ - res = ObjCrystDihedralAngleRestraint(atom1, atom2, atom3, atom4, angle, - sigma, delta, scaled) + res = ObjCrystDihedralAngleRestraint(atom1, atom2, atom3, atom4, angle, sigma, delta, scaled) self._restraints.add(res) return res - def restrainDihedralAngleParameter(self, par, angle, sigma, delta, - scaled = False): + def restrainDihedralAngleParameter(self, par, angle, sigma, delta, scaled=False): """Add a dihedral angle restraint. This creates an instance of ObjCrystDihedralAngleRestraint and adds it @@ -508,11 +502,9 @@ def restrainDihedralAngleParameter(self, par, angle, sigma, delta, 'unrestrain' method. """ - return self.restrainDihedralAngle(par.atom1, par.atom2, par.atom3, - par.atom4, angle, sigma, delta, scaled) + return self.restrainDihedralAngle(par.atom1, par.atom2, par.atom3, par.atom4, angle, sigma, delta, scaled) - def addBondLengthParameter(self, name, atom1, atom2, value = None, const = - False): + def addBondLengthParameter(self, name, atom1, atom2, value=None, const=False): """Add a bond length to the Molecule. This creates a ObjCrystBondLengthParameter to the @@ -536,8 +528,7 @@ def addBondLengthParameter(self, name, atom1, atom2, value = None, const = return par - def addBondAngleParameter(self, name, atom1, atom2, atom3, value = None, - const = False): + def addBondAngleParameter(self, name, atom1, atom2, atom3, value=None, const=False): """Add a bond angle to the Molecule. This creates a ObjCrystBondAngleParameter to the ObjCrystMoleculeParSet @@ -558,14 +549,12 @@ def addBondAngleParameter(self, name, atom1, atom2, atom3, value = None, Returns the new ObjCrystBondAngleParameter. """ - par = ObjCrystBondAngleParameter(name, atom1, atom2, atom3, value, - const) + par = ObjCrystBondAngleParameter(name, atom1, atom2, atom3, value, const) self.addParameter(par) return par - def addDihedralAngleParameter(self, name, atom1, atom2, atom3, atom4, value - = None, const = False): + def addDihedralAngleParameter(self, name, atom1, atom2, atom3, atom4, value=None, const=False): """Add a dihedral angle to the Molecule. This creates a ObjCrystDihedralAngleParameter to the @@ -588,14 +577,15 @@ def addDihedralAngleParameter(self, name, atom1, atom2, atom3, atom4, value Returns the new ObjCrystDihedralAngleParameter. """ - par = ObjCrystDihedralAngleParameter(name, atom1, atom2, atom3, atom4, - value, const) + par = ObjCrystDihedralAngleParameter(name, atom1, atom2, atom3, atom4, value, const) self.addParameter(par) return par + # End class ObjCrystMoleculeParSet + class ObjCrystMolAtomParSet(ObjCrystScattererParSet): """A adaptor for an pyobjcryst.molecule.MolAtom. @@ -634,15 +624,15 @@ def __init__(self, name, scat, parent): # Only wrap this if there is a scattering power if sp is not None: - self.addParameter(ParameterAdapter("Biso", sp, attr = "Biso")) - self.addParameter(ParameterAdapter("B11", sp, attr = "B11")) - self.addParameter(ParameterAdapter("B22", sp, attr = "B22")) - self.addParameter(ParameterAdapter("B33", sp, attr = "B33")) - B12 = ParameterAdapter("B12", sp, attr = "B12") + self.addParameter(ParameterAdapter("Biso", sp, attr="Biso")) + self.addParameter(ParameterAdapter("B11", sp, attr="B11")) + self.addParameter(ParameterAdapter("B22", sp, attr="B22")) + self.addParameter(ParameterAdapter("B33", sp, attr="B33")) + B12 = ParameterAdapter("B12", sp, attr="B12") B21 = ParameterProxy("B21", B12) - B13 = ParameterAdapter("B13", sp, attr = "B13") + B13 = ParameterAdapter("B13", sp, attr="B13") B31 = ParameterProxy("B31", B13) - B23 = ParameterAdapter("B23", sp, attr = "B23") + B23 = ParameterAdapter("B23", sp, attr="B23") B32 = ParameterProxy("B32", B23) self.addParameter(B12) self.addParameter(B21) @@ -667,8 +657,10 @@ def isDummy(self): """Indicate whether this atom is a dummy atom.""" return self.scat.IsDummy() + # End class ObjCrystMolAtomParSet + class ObjCrystMoleculeRestraint(object): """Base class for adapting pyobjcryst Molecule restraints to srfit. @@ -685,7 +677,7 @@ class ObjCrystMoleculeRestraint(object): """ - def __init__(self, res, scaled = False): + def __init__(self, res, scaled=False): """Create a Restraint-like from a pyobjcryst Molecule restraint. res -- The pyobjcryst Molecule restraint. @@ -698,7 +690,7 @@ def __init__(self, res, scaled = False): self.scaled = scaled return - def penalty(self, w = 1.0): + def penalty(self, w=1.0): """Calculate the penalty of the restraint. w -- The point-average chi^2 which is optionally used to scale the @@ -710,8 +702,10 @@ def penalty(self, w = 1.0): penalty *= w return penalty + # End class ObjCrystMoleculeRestraint + class ObjCrystBondLengthRestraint(ObjCrystMoleculeRestraint): """Restrain the distance between two atoms. @@ -728,7 +722,7 @@ class ObjCrystBondLengthRestraint(ObjCrystMoleculeRestraint): """ - def __init__(self, atom1, atom2, length, sigma, delta, scaled = False): + def __init__(self, atom1, atom2, length, sigma, delta, scaled=False): """Create a bond length restraint. atom1 -- First atom (ObjCrystMolAtomParSet) in the bond @@ -751,15 +745,14 @@ def __init__(self, atom1, atom2, length, sigma, delta, scaled = False): return # Give access to the parameters of the restraint - length = property( lambda self: self.res.GetLength0(), - lambda self, val: self.res.SetLength0(val)) - sigma = property( lambda self: self.res.GetLengthSigma(), - lambda self, val: self.res.SetLengthSigma(val)) - delta = property( lambda self: self.res.GetLengthDelta(), - lambda self, val: self.res.SetLengthDelta(val)) + length = property(lambda self: self.res.GetLength0(), lambda self, val: self.res.SetLength0(val)) + sigma = property(lambda self: self.res.GetLengthSigma(), lambda self, val: self.res.SetLengthSigma(val)) + delta = property(lambda self: self.res.GetLengthDelta(), lambda self, val: self.res.SetLengthDelta(val)) + # End class ObjCrystBondLengthRestraint + class ObjCrystBondAngleRestraint(ObjCrystMoleculeRestraint): """Restrain the angle defined by three atoms. @@ -777,8 +770,7 @@ class ObjCrystBondAngleRestraint(ObjCrystMoleculeRestraint): """ - def __init__(self, atom1, atom2, atom3, angle, sigma, delta, scaled = - False): + def __init__(self, atom1, atom2, atom3, angle, sigma, delta, scaled=False): """Create a bond angle restraint. atom1 -- First atom (ObjCrystMolAtomParSet) in the bond angle @@ -798,22 +790,20 @@ def __init__(self, atom1, atom2, atom3, angle, sigma, delta, scaled = self.atom3 = atom3 m = self.atom1.scat.GetMolecule() - res = m.AddBondAngle(atom1.scat, atom2.scat, atom3.scat, angle, - sigma, delta) + res = m.AddBondAngle(atom1.scat, atom2.scat, atom3.scat, angle, sigma, delta) ObjCrystMoleculeRestraint.__init__(self, res, scaled) return # Give access to the parameters of the restraint - angle = property( lambda self: self.res.GetAngle0(), - lambda self, val: self.res.SetAngle0(val)) - sigma = property( lambda self: self.res.GetAngleSigma(), - lambda self, val: self.res.SetAngleSigma(val)) - delta = property( lambda self: self.res.GetAngleDelta(), - lambda self, val: self.res.SetAngleDelta(val)) + angle = property(lambda self: self.res.GetAngle0(), lambda self, val: self.res.SetAngle0(val)) + sigma = property(lambda self: self.res.GetAngleSigma(), lambda self, val: self.res.SetAngleSigma(val)) + delta = property(lambda self: self.res.GetAngleDelta(), lambda self, val: self.res.SetAngleDelta(val)) + # End class ObjCrystBondAngleRestraint + class ObjCrystDihedralAngleRestraint(ObjCrystMoleculeRestraint): """Restrain the dihedral (torsion) angle defined by four atoms. @@ -832,8 +822,7 @@ class ObjCrystDihedralAngleRestraint(ObjCrystMoleculeRestraint): """ - def __init__(self, atom1, atom2, atom3, atom4, angle, sigma, delta, scaled - = False): + def __init__(self, atom1, atom2, atom3, atom4, angle, sigma, delta, scaled=False): """Create a dihedral angle restraint. atom1 -- First atom (ObjCrystMolAtomParSet) in the angle @@ -854,22 +843,20 @@ def __init__(self, atom1, atom2, atom3, atom4, angle, sigma, delta, scaled self.atom4 = atom4 m = self.atom1.scat.GetMolecule() - res = m.AddDihedralAngle(atom1.scat, atom2.scat, atom3.scat, - atom4.scat, angle, sigma, delta) + res = m.AddDihedralAngle(atom1.scat, atom2.scat, atom3.scat, atom4.scat, angle, sigma, delta) ObjCrystMoleculeRestraint.__init__(self, res, scaled) return # Give access to the parameters of the restraint - angle = property( lambda self: self.res.GetAngle0(), - lambda self, val: self.res.SetAngle0(val)) - sigma = property( lambda self: self.res.GetAngleSigma(), - lambda self, val: self.res.SetAngleSigma(val)) - delta = property( lambda self: self.res.GetAngleDelta(), - lambda self, val: self.res.SetAngleDelta(val)) + angle = property(lambda self: self.res.GetAngle0(), lambda self, val: self.res.SetAngle0(val)) + sigma = property(lambda self: self.res.GetAngleSigma(), lambda self, val: self.res.SetAngleSigma(val)) + delta = property(lambda self: self.res.GetAngleDelta(), lambda self, val: self.res.SetAngleDelta(val)) + # End class ObjCrystDihedralAngleRestraint + class StretchModeParameter(Parameter): """Partial Parameter class encapsulating pyobjcryst stretch modes. @@ -887,7 +874,7 @@ class StretchModeParameter(Parameter): """ - def __init__(self, name, value = None, const = False): + def __init__(self, name, value=None, const=False): """Initialization. name -- The name of this Parameter (must be a valid attribute @@ -966,8 +953,10 @@ def notify(self, other=()): Parameter.notify(self, other) return + # End class StretchModeParameter + class ObjCrystBondLengthParameter(StretchModeParameter): """Class for abstracting a bond length in a Molecule to a Parameter. @@ -1016,8 +1005,7 @@ class ObjCrystBondLengthParameter(StretchModeParameter): """ - def __init__(self, name, atom1, atom2, value = None, const = False, mode = - None): + def __init__(self, name, atom1, atom2, value=None, const=False, mode=None): """Create a ObjCrystBondLengthParameter. name -- The name of the ObjCrystBondLengthParameter @@ -1061,7 +1049,7 @@ def __init__(self, name, atom1, atom2, value = None, const = False, mode = return - def setConst(self, const = True, value = None): + def setConst(self, const=True, value=None): """Toggle the Parameter as constant. This sets the underlying ObjCrystMolAtomParSet positions const as well. @@ -1098,6 +1086,7 @@ def getValue(self): # End class ObjCrystBondLengthParameter + class ObjCrystBondAngleParameter(StretchModeParameter): """Class for abstracting a bond angle in a Molecule to a Parameter. @@ -1132,8 +1121,7 @@ class ObjCrystBondAngleParameter(StretchModeParameter): """ - def __init__(self, name, atom1, atom2, atom3, value = None, const = False, - mode = None): + def __init__(self, name, atom1, atom2, atom3, value=None, const=False, mode=None): """Create a ObjCrystBondAngleParameter. name -- The name of the ObjCrystBondAngleParameter. @@ -1155,8 +1143,7 @@ def __init__(self, name, atom1, atom2, atom3, value = None, const = False, # Create the stretch mode self.mode = mode if mode is None: - self.mode = StretchModeBondAngle(atom1.scat, atom2.scat, - atom3.scat, None) + self.mode = StretchModeBondAngle(atom1.scat, atom2.scat, atom3.scat, None) # We only add the last atom. This is the one that will move self.mode.AddAtom(atom3.scat) self.matoms = set([atom3]) @@ -1180,7 +1167,7 @@ def __init__(self, name, atom1, atom2, atom3, value = None, const = False, return - def setConst(self, const = True, value = None): + def setConst(self, const=True, value=None): """Toggle the Parameter as constant. This sets the underlying ObjCrystMolAtomParSet positions const as well. @@ -1208,14 +1195,15 @@ def getValue(self): """ if self._value is None: - val = GetBondAngle(self.atom1.scat, self.atom2.scat, - self.atom3.scat) + val = GetBondAngle(self.atom1.scat, self.atom2.scat, self.atom3.scat) Parameter.setValue(self, val) return self._value + # End class ObjCrystBondAngleParameter + class ObjCrystDihedralAngleParameter(StretchModeParameter): """Class for abstracting a dihedral angle in a Molecule to a Parameter. @@ -1253,8 +1241,7 @@ class ObjCrystDihedralAngleParameter(StretchModeParameter): """ - def __init__(self, name, atom1, atom2, atom3, atom4, value = None, const = - False, mode = None): + def __init__(self, name, atom1, atom2, atom3, atom4, value=None, const=False, mode=None): """Create a ObjCrystDihedralAngleParameter. name -- The name of the ObjCrystDihedralAngleParameter @@ -1298,14 +1285,13 @@ def __init__(self, name, atom1, atom2, atom3, atom4, value = None, const = # We do this last so the atoms are defined before we set any values. if value is None: - value = GetDihedralAngle(atom1.scat, atom2.scat, atom3.scat, - atom4.scat) + value = GetDihedralAngle(atom1.scat, atom2.scat, atom3.scat, atom4.scat) StretchModeParameter.__init__(self, name, value, const) self.setConst(const) return - def setConst(self, const = True, value = None): + def setConst(self, const=True, value=None): """Toggle the Parameter as constant. This sets the underlying ObjCrystMolAtomParSet positions const as well. @@ -1333,14 +1319,15 @@ def getValue(self): """ if self._value is None: - val = GetDihedralAngle(self.atom1.scat, self.atom2.scat, - self.atom3.scat, self.atom4.scat) + val = GetDihedralAngle(self.atom1.scat, self.atom2.scat, self.atom3.scat, self.atom4.scat) Parameter.setValue(self, val) return self._value + # End class ObjCrystDihedralAngleParameter + class ObjCrystCrystalParSet(SrRealParSet): """A adaptor for pyobjcryst.crystal.Crystal instance. @@ -1381,14 +1368,12 @@ def __init__(self, name, cryst): self.stru = cryst self._sgpars = None - self.addParameter(ParameterAdapter("a", self.stru, attr = "a")) - self.addParameter(ParameterAdapter("b", self.stru, attr = "b")) - self.addParameter(ParameterAdapter("c", self.stru, attr = "c")) - self.addParameter(ParameterAdapter("alpha", self.stru, attr = - "alpha")) - self.addParameter(ParameterAdapter("beta", self.stru, attr = "beta")) - self.addParameter(ParameterAdapter("gamma", self.stru, attr = - "gamma")) + self.addParameter(ParameterAdapter("a", self.stru, attr="a")) + self.addParameter(ParameterAdapter("b", self.stru, attr="b")) + self.addParameter(ParameterAdapter("c", self.stru, attr="c")) + self.addParameter(ParameterAdapter("alpha", self.stru, attr="alpha")) + self.addParameter(ParameterAdapter("beta", self.stru, attr="beta")) + self.addParameter(ParameterAdapter("gamma", self.stru, attr="gamma")) # Now we must loop over the scatterers and create parameter sets from # them. @@ -1401,7 +1386,7 @@ def __init__(self, name, cryst): if not name: raise ValueError("Each Scatterer must have a name") if name in snames: - raise ValueError("Scatterer name '%s' is duplicated"%name) + raise ValueError("Scatterer name '%s' is duplicated" % name) # Now create the proper object cname = s.GetClassName() @@ -1410,7 +1395,7 @@ def __init__(self, name, cryst): elif cname == "Molecule": parset = ObjCrystMoleculeParSet(name, s, self) else: - raise TypeError("Unrecognized scatterer '%s'"%cname) + raise TypeError("Unrecognized scatterer '%s'" % cname) self.addParameterSet(parset) self.scatterers.append(parset) @@ -1424,11 +1409,13 @@ def _constrainSpaceGroup(self): return self._sgpars sg = self._createSpaceGroup(self.stru.GetSpaceGroup()) from diffpy.srfit.structure.sgconstraints import _constrainAsSpaceGroup + adpsymbols = ["B11", "B22", "B33", "B12", "B13", "B23"] isosymbol = "Biso" sgoffset = [0, 0, 0] - self._sgpars = _constrainAsSpaceGroup(self, sg, self.scatterers, - sgoffset, adpsymbols = adpsymbols, isosymbol = isosymbol) + self._sgpars = _constrainAsSpaceGroup( + self, sg, self.scatterers, sgoffset, adpsymbols=adpsymbols, isosymbol=isosymbol + ) return self._sgpars sgpars = property(_constrainSpaceGroup) @@ -1445,11 +1432,13 @@ def _createSpaceGroup(sgobjcryst): """ import copy + from diffpy.structure.spacegroups import GetSpaceGroup, SymOp + name = sgobjcryst.GetName() extnstr = ":%s" % sgobjcryst.GetExtension() if name.endswith(extnstr): - name = name[:-len(extnstr)] + name = name[: -len(extnstr)] # Get whatever spacegroup we can get by name. This will set the proper # crystal system. Creating a copy of the singleton from GetSpaceGroup, @@ -1465,7 +1454,7 @@ def _createSpaceGroup(sgobjcryst): for shift, rot in symops: tv = trans + shift tv -= numpy.floor(tv) - sg.symop_list.append( SymOp(rot, tv) ) + sg.symop_list.append(SymOp(rot, tv)) if sgobjcryst.IsCentrosymmetric(): center = sgobjcryst.GetInversionCenter() @@ -1473,7 +1462,7 @@ def _createSpaceGroup(sgobjcryst): for shift, rot in symops: tv = center - trans - shift tv -= numpy.floor(tv) - sg.symop_list.append( SymOp(-rot , tv) ) + sg.symop_list.append(SymOp(-rot, tv)) return sg @@ -1481,6 +1470,7 @@ def _createSpaceGroup(sgobjcryst): def canAdapt(self, stru): """Return whether the structure can be adapted by this class.""" from pyobjcryst.crystal import Crystal + return isinstance(stru, Crystal) def getLattice(self): @@ -1498,4 +1488,5 @@ def getScatterers(self): """ return self.scatterers + # End class ObjCrystCrystalParSet diff --git a/src/diffpy/srfit/structure/sgconstraints.py b/src/diffpy/srfit/structure/sgconstraints.py index 4f64eb3f..cb370adf 100644 --- a/src/diffpy/srfit/structure/sgconstraints.py +++ b/src/diffpy/srfit/structure/sgconstraints.py @@ -17,17 +17,25 @@ import re + import numpy -from diffpy.srfit.fitbase.recipeorganizer import RecipeContainer from diffpy.srfit.fitbase.parameter import ParameterProxy +from diffpy.srfit.fitbase.recipeorganizer import RecipeContainer __all__ = ["constrainAsSpaceGroup"] -def constrainAsSpaceGroup(phase, spacegroup, scatterers = None, - sgoffset = [0, 0, 0], constrainlat = True, constrainadps = True, - adpsymbols = None, isosymbol = "Uiso"): +def constrainAsSpaceGroup( + phase, + spacegroup, + scatterers=None, + sgoffset=[0, 0, 0], + constrainlat=True, + constrainadps=True, + adpsymbols=None, + isosymbol="Uiso", +): """Constrain the structure to the space group. This applies space group constraints to a StructureParSet with P1 @@ -85,14 +93,23 @@ def constrainAsSpaceGroup(phase, spacegroup, scatterers = None, sg = spacegroup if not isinstance(spacegroup, SpaceGroup): sg = GetSpaceGroup(spacegroup) - sgp = _constrainAsSpaceGroup(phase, sg, scatterers, sgoffset, - constrainlat, constrainadps, adpsymbols, isosymbol) + sgp = _constrainAsSpaceGroup( + phase, sg, scatterers, sgoffset, constrainlat, constrainadps, adpsymbols, isosymbol + ) return sgp -def _constrainAsSpaceGroup(phase, sg, scatterers = None, - sgoffset = [0, 0, 0], constrainlat = True, constrainadps = True, - adpsymbols = None, isosymbol = "Uiso"): + +def _constrainAsSpaceGroup( + phase, + sg, + scatterers=None, + sgoffset=[0, 0, 0], + constrainlat=True, + constrainadps=True, + adpsymbols=None, + isosymbol="Uiso", +): """Restricted interface to constrainAsSpaceGroup. Arguments: As constrainAsSpaceGroup, except @@ -107,13 +124,14 @@ def _constrainAsSpaceGroup(phase, sg, scatterers = None, if adpsymbols is None: adpsymbols = stdUsymbols - sgp = SpaceGroupParameters(phase, sg, scatterers, sgoffset, - constrainlat, constrainadps, adpsymbols, isosymbol) + sgp = SpaceGroupParameters(phase, sg, scatterers, sgoffset, constrainlat, constrainadps, adpsymbols, isosymbol) return sgp + # End constrainAsSpaceGroup + class BaseSpaceGroupParameters(RecipeContainer): """Base class for holding space group Parameters. @@ -128,7 +146,7 @@ class is to make it easy to access the free variables of a structure for """ - def __init__(self, name = "sgpars"): + def __init__(self, name="sgpars"): """Create the BaseSpaceGroupParameters object. This initializes the attributes. @@ -137,7 +155,7 @@ def __init__(self, name = "sgpars"): RecipeContainer.__init__(self, name) return - def addParameter(self, par, check = True): + def addParameter(self, par, check=True): """Store a Parameter. par -- The Parameter to be stored. @@ -151,8 +169,10 @@ def addParameter(self, par, check = True): RecipeContainer._addObject(self, par, self._parameters, check) return + # End class BaseSpaceGroupParameters + class SpaceGroupParameters(BaseSpaceGroupParameters): """Class for holding and creating space group Parameters. @@ -183,8 +203,7 @@ class SpaceGroupParameters(BaseSpaceGroupParameters): """ - def __init__(self, phase, sg, scatterers, sgoffset, constrainlat, - constrainadps, adpsymbols, isosymbol): + def __init__(self, phase, sg, scatterers, sgoffset, constrainlat, constrainadps, adpsymbols, isosymbol): """Create the SpaceGroupParameters object. Arguments: @@ -226,13 +245,12 @@ def __init__(self, phase, sg, scatterers, sgoffset, constrainlat, def __iter__(self): """Iterate over top-level parameters.""" - if self._latpars is None or\ - self._xyzpars is None or\ - self._adppars is None: - self._makeConstraints() + if self._latpars is None or self._xyzpars is None or self._adppars is None: + self._makeConstraints() return RecipeContainer.__iter__(self) latpars = property(lambda self: self._getLatPars()) + def _getLatPars(self): """Accessor for _latpars.""" if self._latpars is None: @@ -240,9 +258,10 @@ def _getLatPars(self): return self._latpars xyzpars = property(lambda self: self._getXYZPars()) + def _getXYZPars(self): """Accessor for _xyzpars.""" - positions = [] + positions = [] for scatterer in self.scatterers: xyz = [scatterer.x, scatterer.y, scatterer.z] positions.append([p.value for p in xyz]) @@ -251,9 +270,10 @@ def _getXYZPars(self): return self._xyzpars adppars = property(lambda self: self._getADPPars()) + def _getADPPars(self): """Accessor for _adppars.""" - positions = [] + positions = [] for scatterer in self.scatterers: xyz = [scatterer.x, scatterer.y, scatterer.z] positions.append([p.value for p in xyz]) @@ -274,7 +294,7 @@ def _makeConstraints(self): scatterers = self.scatterers # Prepare positions - positions = [] + positions = [] for scatterer in scatterers: xyz = [scatterer.x, scatterer.y, scatterer.z] positions.append([p.value for p in xyz]) @@ -285,7 +305,6 @@ def _makeConstraints(self): return - def _clearConstraints(self): """Clear old constraints. @@ -309,8 +328,7 @@ def _clearConstraints(self): if self.constrainlat: lattice = phase.getLattice() - latpars = [lattice.a, lattice.b, lattice.c, lattice.alpha, - lattice.beta, lattice.gamma] + latpars = [lattice.a, lattice.b, lattice.c, lattice.alpha, lattice.beta, lattice.gamma] for par in latpars: if lattice.isConstrained(par): lattice.unconstrain(par) @@ -338,7 +356,8 @@ def _clearConstraints(self): def _constrainLattice(self): """Constrain the lattice parameters.""" - if not self.constrainlat: return + if not self.constrainlat: + return phase = self.phase sg = self.sg @@ -354,8 +373,7 @@ def _constrainLattice(self): # Now get the unconstrained, non-constant lattice pars and store them. self._latpars = BaseSpaceGroupParameters("latpars") - latpars = [lattice.a, lattice.b, lattice.c, lattice.alpha, - lattice.beta, lattice.gamma] + latpars = [lattice.a, lattice.b, lattice.c, lattice.alpha, lattice.beta, lattice.gamma] pars = [p for p in latpars if not p.const and not p.constrained] for par in pars: # FIXME - the original parameter will still appear as @@ -385,9 +403,9 @@ def _constrainXYZs(self, positions): self._xyzpars = BaseSpaceGroupParameters("xyzpars") # Make proxies to the free xyz parameters - xyznames = [name[:1]+"_"+name[1:] for name, val in g.pospars] + xyznames = [name[:1] + "_" + name[1:] for name, val in g.pospars] for pname in xyznames: - name, idx = pname.rsplit('_', 1) + name, idx = pname.rsplit("_", 1) idx = int(idx) par = scatterers[idx].get(name) newpar = self.__addPar(pname, par) @@ -400,8 +418,7 @@ def _constrainXYZs(self, positions): # Extract the constraint equation from the formula for parname, formula in fp.items(): - _makeconstraint(parname, formula, scatterer, idx, - self._parameters) + _makeconstraint(parname, formula, scatterer, idx, self._parameters) return @@ -412,10 +429,10 @@ def _constrainADPs(self, positions): """ - from diffpy.structure.symmetryutilities import stdUsymbols - from diffpy.structure.symmetryutilities import SymmetryConstraints + from diffpy.structure.symmetryutilities import SymmetryConstraints, stdUsymbols - if not self.constrainadps: return + if not self.constrainadps: + return sg = self.sg sgoffset = self.sgoffset @@ -438,10 +455,10 @@ def _constrainADPs(self, positions): nonadps.append(sidx) continue - Uij = numpy.zeros((3,3), dtype=float) + Uij = numpy.zeros((3, 3), dtype=float) for idx, par in enumerate(pars): i, j = _idxtoij[idx] - Uij[i,j] = Uij[j,i] = par.getValue() + Uij[i, j] = Uij[j, i] = par.getValue() Uijs.append(Uij) @@ -461,7 +478,7 @@ def _constrainADPs(self, positions): isoidx = [] isonames = [] for pname in adpnames: - name, idx = pname.rsplit('_', 1) + name, idx = pname.rsplit("_", 1) idx = int(idx) # Check for isotropic ADPs scatterer = scatterers[idx] @@ -482,24 +499,24 @@ def _constrainADPs(self, positions): # Constrain dependent isotropics for idx, isoname in zip(isoidx[:], isonames): for j in g.coremap[idx]: - if j == idx: continue + if j == idx: + continue isoidx.append(j) scatterer = scatterers[j] - scatterer.constrain(isosymbol, isoname, ns = self._parameters) + scatterer.constrain(isosymbol, isoname, ns=self._parameters) fadp = g.UFormulas(adpnames) # Constrain dependent anisotropics. We use the fact that an # anisotropic cannot be dependent on an isotropic. for idx, tmp in enumerate(zip(scatterers, fadp)): - if idx in isoidx: continue + if idx in isoidx: + continue scatterer, fa = tmp # Extract the constraint equation from the formula for stdparname, formula in fa.items(): pname = adpmap[stdparname] - _makeconstraint(pname, formula, scatterer, idx, - self._parameters) - + _makeconstraint(pname, formula, scatterer, idx, self._parameters) def __addPar(self, parname, par): """Constrain a parameter via proxy with a specified name @@ -512,18 +529,19 @@ def __addPar(self, parname, par): self.addParameter(newpar) return newpar + # End class SpaceGroupParameters # crystal system rules # ref: Benjamin, W. A., Introduction to crystallography, # New York (1969), p.60 -def _constrainTriclinic(lattice): - """Make constraints for Triclinic systems. - """ +def _constrainTriclinic(lattice): + """Make constraints for Triclinic systems.""" return + def _constrainMonoclinic(lattice): """Make constraints for Monoclinic systems. @@ -532,7 +550,8 @@ def _constrainMonoclinic(lattice): """ afactor = 1 - if lattice.angunits == "rad": afactor = deg2rad + if lattice.angunits == "rad": + afactor = deg2rad ang90 = 90.0 * afactor lattice.alpha.setConst(True, ang90) beta = lattice.beta.getValue() @@ -544,6 +563,7 @@ def _constrainMonoclinic(lattice): lattice.beta.setConst(True, ang90) return + def _constrainOrthorhombic(lattice): """Make constraints for Orthorhombic systems. @@ -551,13 +571,15 @@ def _constrainOrthorhombic(lattice): """ afactor = 1 - if lattice.angunits == "rad": afactor = deg2rad + if lattice.angunits == "rad": + afactor = deg2rad ang90 = 90.0 * afactor lattice.alpha.setConst(True, ang90) lattice.beta.setConst(True, ang90) lattice.gamma.setConst(True, ang90) return + def _constrainTetragonal(lattice): """Make constraints for Tetragonal systems. @@ -565,7 +587,8 @@ def _constrainTetragonal(lattice): """ afactor = 1 - if lattice.angunits == "rad": afactor = deg2rad + if lattice.angunits == "rad": + afactor = deg2rad ang90 = 90.0 * afactor lattice.alpha.setConst(True, ang90) lattice.beta.setConst(True, ang90) @@ -573,6 +596,7 @@ def _constrainTetragonal(lattice): lattice.constrain(lattice.b, lattice.a) return + def _constrainTrigonal(lattice): """Make constraints for Trigonal systems. @@ -582,7 +606,8 @@ def _constrainTrigonal(lattice): """ afactor = 1 - if lattice.angunits == "rad": afactor = deg2rad + if lattice.angunits == "rad": + afactor = deg2rad ang90 = 90.0 * afactor ang120 = 120.0 * afactor if lattice.gamma.getValue() == ang120: @@ -597,6 +622,7 @@ def _constrainTrigonal(lattice): lattice.constrain(lattice.gamma, lattice.alpha) return + def _constrainHexagonal(lattice): """Make constraints for Hexagonal systems. @@ -605,7 +631,8 @@ def _constrainHexagonal(lattice): """ afactor = 1 - if lattice.angunits == "rad": afactor = deg2rad + if lattice.angunits == "rad": + afactor = deg2rad ang90 = 90.0 * afactor ang120 = 120.0 * afactor lattice.constrain(lattice.b, lattice.a) @@ -614,6 +641,7 @@ def _constrainHexagonal(lattice): lattice.gamma.setConst(True, ang120) return + def _constrainCubic(lattice): """Make constraints for Cubic systems. @@ -621,7 +649,8 @@ def _constrainCubic(lattice): """ afactor = 1 - if lattice.angunits == "rad": afactor = deg2rad + if lattice.angunits == "rad": + afactor = deg2rad ang90 = 90.0 * afactor lattice.constrain(lattice.b, lattice.a) lattice.constrain(lattice.c, lattice.a) @@ -630,19 +659,21 @@ def _constrainCubic(lattice): lattice.gamma.setConst(True, ang90) return + # This is used to map the correct crystal system to the proper constraint # function. _constraintMap = { - "Triclinic" : _constrainTriclinic, - "Monoclinic" : _constrainMonoclinic, - "Orthorhombic" : _constrainOrthorhombic, - "Tetragonal" : _constrainTetragonal, - "Trigonal" : _constrainTrigonal, - "Hexagonal" : _constrainHexagonal, - "Cubic" : _constrainCubic + "Triclinic": _constrainTriclinic, + "Monoclinic": _constrainMonoclinic, + "Orthorhombic": _constrainOrthorhombic, + "Tetragonal": _constrainTetragonal, + "Trigonal": _constrainTrigonal, + "Hexagonal": _constrainHexagonal, + "Cubic": _constrainCubic, } -def _makeconstraint(parname, formula, scatterer, idx, ns = {}): + +def _makeconstraint(parname, formula, scatterer, idx, ns={}): """Constrain a parameter according to a formula. parname -- Name of parameter @@ -659,10 +690,10 @@ def _makeconstraint(parname, formula, scatterer, idx, ns = {}): if par is None: return - compname = "%s_%i"%(parname, idx) + compname = "%s_%i" % (parname, idx) # Check to see if this parameter is free - pat = r'%s *([+-] *\d+)?$' % compname + pat = r"%s *([+-] *\d+)?$" % compname if re.match(pat, formula): return par @@ -675,9 +706,10 @@ def _makeconstraint(parname, formula, scatterer, idx, ns = {}): # If we got here, then we have a constraint equation # Fix any division issues formula = formula.replace("/", "*1.0/") - scatterer.constrain(par, formula, ns = ns) + scatterer.constrain(par, formula, ns=ns) return + def _getFloat(formula): """Get a float from a formula string, or None if this is not possible.""" try: @@ -685,6 +717,7 @@ def _getFloat(formula): except NameError: return None + # Constants needed above _idxtoij = [(0, 0), (1, 1), (2, 2), (0, 1), (0, 2), (1, 2)] deg2rad = numpy.pi / 180 diff --git a/src/diffpy/srfit/structure/srrealparset.py b/src/diffpy/srfit/structure/srrealparset.py index e1376288..c3c505aa 100644 --- a/src/diffpy/srfit/structure/srrealparset.py +++ b/src/diffpy/srfit/structure/srrealparset.py @@ -42,7 +42,7 @@ def __init__(self, *args, **kw): self.stru = None return - def restrainBVS(self, sig = 1, scaled = False): + def restrainBVS(self, sig=1, scaled=False): """Restrain the bond-valence sum to zero. This adds a penalty to the cost function equal to @@ -70,7 +70,7 @@ def restrainBVS(self, sig = 1, scaled = False): # Return the Restraint object return res - def useSymmetry(self, use = True): + def useSymmetry(self, use=True): """Set this structure to use symmetry. This determines how the structure is treated by SrReal calculators. @@ -91,6 +91,7 @@ def _getSrRealStructure(self): """ from diffpy.srreal.structureadapter import nosymmetry + if self._usesymmetry: return self.stru return nosymmetry(self.stru) diff --git a/src/diffpy/srfit/tests/__init__.py b/src/diffpy/srfit/tests/__init__.py index 845b5c39..81caf417 100644 --- a/src/diffpy/srfit/tests/__init__.py +++ b/src/diffpy/srfit/tests/__init__.py @@ -16,8 +16,8 @@ """Unit tests for diffpy.srfit. """ -import unittest import logging +import unittest # create logger instance for the tests subpackage logging.basicConfig() @@ -25,8 +25,8 @@ del logging -def testsuite(pattern=''): - '''Create a unit tests suite for diffpy.srfit package. +def testsuite(pattern=""): + """Create a unit tests suite for diffpy.srfit package. Parameters ---------- @@ -39,14 +39,16 @@ def testsuite(pattern=''): ------- suite : `unittest.TestSuite` The TestSuite object containing the matching tests. - ''' + """ import re - from os.path import dirname from itertools import chain + from os.path import dirname + from pkg_resources import resource_filename + loader = unittest.defaultTestLoader - thisdir = resource_filename(__name__, '') - depth = __name__.count('.') + 1 + thisdir = resource_filename(__name__, "") + depth = __name__.count(".") + 1 topdir = thisdir for i in range(depth): topdir = dirname(topdir) @@ -56,12 +58,12 @@ def testsuite(pattern=''): rx = re.compile(pattern) tsuites = list(chain.from_iterable(suite_all)) tsok = all(isinstance(ts, unittest.TestSuite) for ts in tsuites) - if not tsok: # pragma: no cover + if not tsok: # pragma: no cover return suite_all tcases = chain.from_iterable(tsuites) for tc in tcases: - tcwords = tc.id().split('.') - shortname = '.'.join(tcwords[-3:]) + tcwords = tc.id().split(".") + shortname = ".".join(tcwords[-3:]) if rx.search(shortname): suite.addTest(tc) # verify all tests are found for an empty pattern. @@ -70,12 +72,12 @@ def testsuite(pattern=''): def test(): - '''Execute all unit tests for the diffpy.srfit package. + """Execute all unit tests for the diffpy.srfit package. Returns ------- result : `unittest.TestResult` - ''' + """ suite = testsuite() runner = unittest.TextTestRunner() result = runner.run(suite) diff --git a/src/diffpy/srfit/tests/run.py b/src/diffpy/srfit/tests/run.py index f1c83fa0..a47c886e 100644 --- a/src/diffpy/srfit/tests/run.py +++ b/src/diffpy/srfit/tests/run.py @@ -19,15 +19,19 @@ """ -if __name__ == '__main__': +if __name__ == "__main__": import sys + # show warnings by default if not sys.warnoptions: - import os, warnings + import os + import warnings + warnings.simplefilter("default") # also affect subprocesses os.environ["PYTHONWARNINGS"] = "default" from diffpy.srfit.tests import test + # produce zero exit code for a successful test sys.exit(not test().wasSuccessful()) diff --git a/src/diffpy/srfit/tests/speedtest.py b/src/diffpy/srfit/tests/speedtest.py index 373d5843..b822f968 100644 --- a/src/diffpy/srfit/tests/speedtest.py +++ b/src/diffpy/srfit/tests/speedtest.py @@ -18,11 +18,11 @@ from __future__ import print_function import random + import numpy -import diffpy.srfit.equation.visitors as visitors import diffpy.srfit.equation.literals as literals - +import diffpy.srfit.equation.visitors as visitors from diffpy.srfit.tests.utils import _makeArgs x = numpy.arange(0, 20, 0.05) @@ -57,7 +57,7 @@ def makeLazyEquation(): mult2.addLiteral(exp) v2.setValue(x) - v3.setValue(50*x) + v3.setValue(50 * x) v5.setValue(2.11) v6.setValue(numpy.e) @@ -75,23 +75,27 @@ def _f(a, b, c, d, e): return _f + def makeEquation1(): """Make the same equation as the lazy one.""" - y = 50*x + y = 50 * x def _f(a, b, c, d, e): - return ((a+x)*(y-b))**c * d**e + return ((a + x) * (y - b)) ** c * d**e return _f + def timeFunction(f, *args, **kw): """Time a function in ms.""" import time + t1 = time.time() f(*args, **kw) t2 = time.time() - return (t2-t1)*1000 + return (t2 - t1) * 1000 + def speedTest1(): f1 = makeLazyEquation() @@ -102,7 +106,7 @@ def speedTest1(): total1 = 0 total2 = 0 for i in range(len(args)): - args[i] = 10*random.random() + args[i] = 10 * random.random() print("Changing argument %i" % (i + 1)) t1 = timeFunction(f1, *args) t2 = timeFunction(f2, *args) @@ -114,11 +118,13 @@ def speedTest1(): print("Totals:") print("lazy", total1) print("regular", total2) - print("Ratio (lazy/regular)", total1/total2) + print("Ratio (lazy/regular)", total1 / total2) + -def speedTest2(mutate = 2): +def speedTest2(mutate=2): from diffpy.srfit.equation.builder import EquationFactory + factory = EquationFactory() x = numpy.arange(0, 20, 0.05) @@ -144,17 +150,19 @@ def speedTest2(mutate = 2): eq.b7.setValue(2.0) eq.b8.setValue(2.0) - from numpy import exp - from numpy import polyval + from numpy import exp, polyval + def f(A0, qsig, sigma1, sigma2, b1, b2, b3, b4, b5, b6, b7, b8): - return A0*exp(-(x*qsig)**2)*(exp(-((x-1.0)/sigma1)**2)+exp(-((x-2.0)/sigma2)**2)) + polyval([b8, b7, b6, b5,b4,b3,b2,b1],x) + return A0 * exp(-((x * qsig) ** 2)) * ( + exp(-(((x - 1.0) / sigma1) ** 2)) + exp(-(((x - 2.0) / sigma2) ** 2)) + ) + polyval([b8, b7, b6, b5, b4, b3, b2, b1], x) tnpy = 0 teq = 0 # Randomly change variables numargs = len(eq.args) choices = range(numargs) - args = [0.0]*(len(eq.args)) + args = [0.0] * (len(eq.args)) # The call-loop random.seed() @@ -174,15 +182,15 @@ def f(A0, qsig, sigma1, sigma2, b1, b2, b3, b4, b5, b6, b7, b8): tnpy += timeFunction(f, *args) teq += timeFunction(eq, *args) - print("Average call time (%i calls, %i mutations/call):" % - (numcalls, mutate)) - print("numpy: ", tnpy/numcalls) - print("equation: ", teq/numcalls) - print("ratio: ", teq/tnpy) + print("Average call time (%i calls, %i mutations/call):" % (numcalls, mutate)) + print("numpy: ", tnpy / numcalls) + print("equation: ", teq / numcalls) + print("ratio: ", teq / tnpy) return -def speedTest3(mutate = 2): + +def speedTest3(mutate=2): """Test wrt sympy. Results - sympy is 10 to 24 times faster without using arrays (ouch!). @@ -192,6 +200,7 @@ def speedTest3(mutate = 2): """ from diffpy.srfit.equation.builder import EquationFactory + factory = EquationFactory() x = numpy.arange(0, 20, 0.05) @@ -217,17 +226,25 @@ def speedTest3(mutate = 2): eq.b7.setValue(2.0) eq.b8.setValue(2.0) - from sympy import var, exp, lambdify from numpy import polyval - A0, qsig, sigma1, sigma2, b1, b2, b3, b4, b5, b6, b7, b8, xx = vars = var("A0 qsig sigma1 sigma2 b1 b2 b3 b4 b5 b6 b7 b8 xx") - f = lambdify(vars, A0*exp(-(xx*qsig)**2)*(exp(-((xx-1.0)/sigma1)**2)+exp(-((xx-2.0)/sigma2)**2)) + polyval([b1, b2, b3, b4, b5, b6, b7, b8], xx), "numpy") + from sympy import exp, lambdify, var + + A0, qsig, sigma1, sigma2, b1, b2, b3, b4, b5, b6, b7, b8, xx = vars = var( + "A0 qsig sigma1 sigma2 b1 b2 b3 b4 b5 b6 b7 b8 xx" + ) + f = lambdify( + vars, + A0 * exp(-((xx * qsig) ** 2)) * (exp(-(((xx - 1.0) / sigma1) ** 2)) + exp(-(((xx - 2.0) / sigma2) ** 2))) + + polyval([b1, b2, b3, b4, b5, b6, b7, b8], xx), + "numpy", + ) tnpy = 0 teq = 0 # Randomly change variables numargs = len(eq.args) choices = range(numargs) - args = [1.0]*(len(eq.args)) + args = [1.0] * (len(eq.args)) args.append(x) # The call-loop @@ -248,15 +265,15 @@ def speedTest3(mutate = 2): teq += timeFunction(eq, *(args[:-1])) tnpy += timeFunction(f, *args) - print("Average call time (%i calls, %i mutations/call):" % - (numcalls, mutate)) - print("sympy: ", tnpy/numcalls) - print("equation: ", teq/numcalls) - print("ratio: ", teq/tnpy) + print("Average call time (%i calls, %i mutations/call):" % (numcalls, mutate)) + print("sympy: ", tnpy / numcalls) + print("equation: ", teq / numcalls) + print("ratio: ", teq / tnpy) return -def speedTest4(mutate = 2): + +def speedTest4(mutate=2): """Test wrt sympy. Results - sympy is 10 to 24 times faster without using arrays (ouch!). @@ -266,6 +283,7 @@ def speedTest4(mutate = 2): """ from diffpy.srfit.equation.builder import EquationFactory + factory = EquationFactory() x = numpy.arange(0, 20, 0.05) @@ -276,8 +294,9 @@ def speedTest4(mutate = 2): factory.registerConstant("x", x) eq = factory.makeEquation(eqstr) - from sympy import var, lambdify from numpy import polyval + from sympy import lambdify, var + b1, b2, b3, b4, b5, b6, b7, b8, xx = vars = var("b1 b2 b3 b4 b5 b6 b7 b8 xx") f = lambdify(vars, polyval([b1, b2, b3, b4, b5, b6, b7, b8], xx), "numpy") @@ -286,7 +305,7 @@ def speedTest4(mutate = 2): # Randomly change variables numargs = len(eq.args) choices = range(numargs) - args = [1.0]*(len(eq.args)) + args = [1.0] * (len(eq.args)) args.append(x) # The call-loop @@ -307,18 +326,19 @@ def speedTest4(mutate = 2): teq += timeFunction(eq, *(args[:-1])) tnpy += timeFunction(f, *args) - print("Average call time (%i calls, %i mutations/call):" % - (numcalls, mutate)) - print("sympy: ", tnpy/numcalls) - print("equation: ", teq/numcalls) - print("ratio: ", teq/tnpy) + print("Average call time (%i calls, %i mutations/call):" % (numcalls, mutate)) + print("sympy: ", tnpy / numcalls) + print("equation: ", teq / numcalls) + print("ratio: ", teq / tnpy) return -def weightedTest(mutate = 2): + +def weightedTest(mutate=2): """Show the benefits of a properly balanced equation tree.""" from diffpy.srfit.equation.builder import EquationFactory + factory = EquationFactory() x = numpy.arange(0, 10, 0.01) @@ -338,20 +358,21 @@ def weightedTest(mutate = 2): eq.b7.setValue(2.0) eq.b8.setValue(2.0) - #scale = visitors.NodeWeigher() - #eq.root.identify(scale) - #print(scale.output) + # scale = visitors.NodeWeigher() + # eq.root.identify(scale) + # print(scale.output) from numpy import polyval + def f(b1, b2, b3, b4, b5, b6, b7, b8): - return polyval([b8, b7, b6, b5,b4,b3,b2,b1],x) + return polyval([b8, b7, b6, b5, b4, b3, b2, b1], x) tnpy = 0 teq = 0 # Randomly change variables numargs = len(eq.args) choices = range(numargs) - args = [0.1]*numargs + args = [0.1] * numargs # The call-loop random.seed() @@ -367,23 +388,24 @@ def f(b1, b2, b3, b4, b5, b6, b7, b8): c.remove(idx) args[idx] = random.random() - #print(args) + # print(args) # Time the different functions with these arguments teq += timeFunction(eq, *args) tnpy += timeFunction(f, *args) - print("Average call time (%i calls, %i mutations/call):" % - (numcalls, mutate)) - print("numpy: ", tnpy/numcalls) - print("equation: ", teq/numcalls) - print("ratio: ", teq/tnpy) + print("Average call time (%i calls, %i mutations/call):" % (numcalls, mutate)) + print("numpy: ", tnpy / numcalls) + print("equation: ", teq / numcalls) + print("ratio: ", teq / tnpy) return + def profileTest(): from diffpy.srfit.builder import EquationFactory + factory = EquationFactory() x = numpy.arange(0, 10, 0.001) @@ -406,7 +428,7 @@ def profileTest(): mutate = 8 numargs = len(eq.args) choices = range(numargs) - args = [0.1]*numargs + args = [0.1] * numargs # The call-loop random.seed() diff --git a/src/diffpy/srfit/tests/testbuilder.py b/src/diffpy/srfit/tests/testbuilder.py index 15a7ae84..9cd08f5f 100644 --- a/src/diffpy/srfit/tests/testbuilder.py +++ b/src/diffpy/srfit/tests/testbuilder.py @@ -21,8 +21,7 @@ import diffpy.srfit.equation.builder as builder import diffpy.srfit.equation.literals as literals -from diffpy.srfit.tests.utils import _makeArgs -from diffpy.srfit.tests.utils import noObserversInGlobalBuilders +from diffpy.srfit.tests.utils import _makeArgs, noObserversInGlobalBuilders class TestBuilder(unittest.TestCase): @@ -52,7 +51,6 @@ def testRegisterArg(self): self.assertTrue(noObserversInGlobalBuilders()) return - def testRegisterOperator(self): """Try to use an operator without arguments in an equation.""" @@ -86,13 +84,13 @@ def testRegisterOperator(self): self.assertTrue(noObserversInGlobalBuilders()) return - def testSwapping(self): def g1(v1, v2, v3, v4): return (v1 + v2) * (v3 + v4) + def g2(v1): - return 0.5*v1 + return 0.5 * v1 factory = builder.EquationFactory() v1, v2, v3, v4, v5 = _makeArgs(5) @@ -149,7 +147,7 @@ def g2(v1): def testParseEquation(self): - from numpy import sin, divide, sqrt, array_equal, e + from numpy import array_equal, divide, e, sin, sqrt factory = builder.EquationFactory() @@ -163,8 +161,8 @@ def testParseEquation(self): eq.x.setValue(x) eq.B.setValue(B) eq.C.setValue(C) - f = lambda A, x, B, C: A*sin(0.5*x)+divide(B,C) - self.assertTrue(array_equal(eq(), f(A,x,B,C))) + f = lambda A, x, B, C: A * sin(0.5 * x) + divide(B, C) + self.assertTrue(array_equal(eq(), f(A, x, B, C))) # Make sure that the arguments of eq are listed in the order in which # they appear in the equations. @@ -176,8 +174,8 @@ def testParseEquation(self): sigma = 0.1 eq.x.setValue(x) eq.sigma.setValue(sigma) - f = lambda x, sigma : sqrt(e**(-0.5*(x/sigma)**2)) - self.assertTrue(numpy.allclose(eq(), f(x,sigma))) + f = lambda x, sigma: sqrt(e ** (-0.5 * (x / sigma) ** 2)) + self.assertTrue(numpy.allclose(eq(), f(x, sigma))) self.assertEqual(eq.args, [eq.x, eq.sigma]) @@ -186,14 +184,14 @@ def testParseEquation(self): eq = factory.makeEquation("sqrt(e**(-0.5*(x/sigma)**2))") self.assertTrue("sigma" in eq.argdict) self.assertTrue("x" not in eq.argdict) - self.assertTrue(numpy.allclose(eq(sigma=sigma), f(x,sigma))) + self.assertTrue(numpy.allclose(eq(sigma=sigma), f(x, sigma))) self.assertEqual(eq.args, [eq.sigma]) # Equation with user-defined functions factory.registerFunction("myfunc", eq, ["sigma"]) eq2 = factory.makeEquation("c*myfunc(sigma)") - self.assertTrue(numpy.allclose(eq2(c=2, sigma=sigma), 2*f(x,sigma))) + self.assertTrue(numpy.allclose(eq2(c=2, sigma=sigma), 2 * f(x, sigma))) self.assertTrue("sigma" in eq2.argdict) self.assertTrue("c" in eq2.argdict) self.assertEqual(eq2.args, [eq2.c, eq2.sigma]) @@ -201,35 +199,32 @@ def testParseEquation(self): self.assertTrue(noObserversInGlobalBuilders()) return - def test_parse_constant(self): - """Verify parsing of constant numeric expressions. - """ + """Verify parsing of constant numeric expressions.""" factory = builder.EquationFactory() - eq = factory.makeEquation('3.12 + 2') + eq = factory.makeEquation("3.12 + 2") self.assertTrue(isinstance(eq, builder.Equation)) self.assertEqual(set(), factory.equations) self.assertEqual(5.12, eq()) self.assertRaises(ValueError, eq, 3) return - def testBuildEquation(self): from numpy import array_equal # simple equation sin = builder.getBuilder("sin") - a = builder.ArgumentBuilder(name="a", value = 1) - A = builder.ArgumentBuilder(name="A", value = 2) + a = builder.ArgumentBuilder(name="a", value=1) + A = builder.ArgumentBuilder(name="A", value=2) x = numpy.arange(0, numpy.pi, 0.1) - beq = A*sin(a*x) + beq = A * sin(a * x) eq = beq.getEquation() self.assertTrue("a" in eq.argdict) self.assertTrue("A" in eq.argdict) - self.assertTrue(array_equal(eq(), 2*numpy.sin(x))) + self.assertTrue(array_equal(eq(), 2 * numpy.sin(x))) self.assertEqual(eq.args, [eq.A, eq.a]) @@ -238,13 +233,13 @@ def testBuildEquation(self): # custom function def _f(a, b): - return (a-b)*1.0/(a+b) + return (a - b) * 1.0 / (a + b) f = builder.wrapFunction("f", _f, 2, 1) - a = builder.ArgumentBuilder(name="a", value = 2) - b = builder.ArgumentBuilder(name="b", value = 1) + a = builder.ArgumentBuilder(name="a", value=2) + b = builder.ArgumentBuilder(name="b", value=1) - beq = sin(f(a,b)) + beq = sin(f(a, b)) eq = beq.getEquation() self.assertEqual(eq(), numpy.sin(_f(2, 1))) @@ -252,32 +247,32 @@ def _f(a, b): sqrt = builder.getBuilder("sqrt") e = numpy.e _x = numpy.arange(0, 1, 0.05) - x = builder.ArgumentBuilder(name="x", value = _x, const = True) - sigma = builder.ArgumentBuilder(name="sigma", value = 0.1) - beq = sqrt(e**(-0.5*(x/sigma)**2)) + x = builder.ArgumentBuilder(name="x", value=_x, const=True) + sigma = builder.ArgumentBuilder(name="sigma", value=0.1) + beq = sqrt(e ** (-0.5 * (x / sigma) ** 2)) eq = beq.getEquation() - f = lambda x, sigma : sqrt(e**(-0.5*(x/sigma)**2)) - self.assertTrue(numpy.allclose(eq(), numpy.sqrt(e**(-0.5*(_x/0.1)**2)))) + f = lambda x, sigma: sqrt(e ** (-0.5 * (x / sigma) ** 2)) + self.assertTrue(numpy.allclose(eq(), numpy.sqrt(e ** (-0.5 * (_x / 0.1) ** 2)))) # Equation with Equation - A = builder.ArgumentBuilder(name="A", value = 2) - B = builder.ArgumentBuilder(name="B", value = 4) + A = builder.ArgumentBuilder(name="A", value=2) + B = builder.ArgumentBuilder(name="B", value=4) beq = A + B eq = beq.getEquation() E = builder.wrapOperator("eq", eq) - eq2 = (2*E).getEquation() + eq2 = (2 * E).getEquation() # Make sure these evaulate to the same thing self.assertEqual(eq.args, [A.literal, B.literal]) - self.assertEqual(2*eq(), eq2()) + self.assertEqual(2 * eq(), eq2()) # Pass new arguments to the equation - C = builder.ArgumentBuilder(name="C", value = 5) - D = builder.ArgumentBuilder(name="D", value = 6) - eq3 = (E(C, D)+1).getEquation() + C = builder.ArgumentBuilder(name="C", value=5) + D = builder.ArgumentBuilder(name="D", value=6) + eq3 = (E(C, D) + 1).getEquation() self.assertEqual(12, eq3()) # Pass old and new arguments to the equation # If things work right, A has been given the value of C in the last # evaluation (5) - eq4 = (3*E(A, D)-1).getEquation() + eq4 = (3 * E(A, D) - 1).getEquation() self.assertEqual(32, eq4()) # Try to pass the wrong number of arguments self.assertRaises(ValueError, E, A) diff --git a/src/diffpy/srfit/tests/testcharacteristicfunctions.py b/src/diffpy/srfit/tests/testcharacteristicfunctions.py index e619f4fc..62e4d1da 100644 --- a/src/diffpy/srfit/tests/testcharacteristicfunctions.py +++ b/src/diffpy/srfit/tests/testcharacteristicfunctions.py @@ -19,52 +19,52 @@ import numpy -from diffpy.srfit.tests.utils import has_sas, _msg_nosas from diffpy.srfit.sas.sasimport import sasimport +from diffpy.srfit.tests.utils import _msg_nosas, has_sas # Global variables to be assigned in setUp cf = None # ---------------------------------------------------------------------------- + @unittest.skipUnless(has_sas, _msg_nosas) class TestSASCF(unittest.TestCase): def setUp(self): global cf import diffpy.srfit.pdf.characteristicfunctions as cf - return + return def testSphere(self): radius = 25 # Calculate sphere cf from SphereModel - SphereModel = sasimport('sas.models.SphereModel').SphereModel + SphereModel = sasimport("sas.models.SphereModel").SphereModel model = SphereModel() model.setParam("radius", radius) ff = cf.SASCF("sphere", model) - r = numpy.arange(1, 60, 0.1, dtype = float) + r = numpy.arange(1, 60, 0.1, dtype=float) fr1 = ff(r) # Calculate sphere cf analytically - fr2 = cf.sphericalCF(r, 2*radius) + fr2 = cf.sphericalCF(r, 2 * radius) diff = fr1 - fr2 res = numpy.dot(diff, diff) res /= numpy.dot(fr2, fr2) self.assertAlmostEqual(0, res, 4) return - def testSpheroid(self): prad = 20.9 erad = 33.114 # Calculate cf from EllipsoidModel - EllipsoidModel = sasimport('sas.models.EllipsoidModel').EllipsoidModel + EllipsoidModel = sasimport("sas.models.EllipsoidModel").EllipsoidModel model = EllipsoidModel() model.setParam("radius_a", prad) model.setParam("radius_b", erad) ff = cf.SASCF("spheroid", model) - r = numpy.arange(0, 100, 1/numpy.pi, dtype = float) + r = numpy.arange(0, 100, 1 / numpy.pi, dtype=float) fr1 = ff(r) # Calculate cf analytically @@ -75,17 +75,16 @@ def testSpheroid(self): self.assertAlmostEqual(0, res, 4) return - def testShell(self): radius = 19.2 thickness = 7.8 # Calculate cf from VesicleModel - VesicleModel = sasimport('sas.models.VesicleModel').VesicleModel + VesicleModel = sasimport("sas.models.VesicleModel").VesicleModel model = VesicleModel() model.setParam("radius", radius) model.setParam("thickness", thickness) ff = cf.SASCF("vesicle", model) - r = numpy.arange(0, 99.45, 0.1, dtype = float) + r = numpy.arange(0, 99.45, 0.1, dtype=float) fr1 = ff(r) # Calculate sphere cf analytically @@ -96,23 +95,22 @@ def testShell(self): self.assertAlmostEqual(0, res, 4) return - def testCylinder(self): """Make sure cylinder works over different r-ranges""" radius = 100 length = 30 - CylinderModel = sasimport('sas.models.CylinderModel').CylinderModel + CylinderModel = sasimport("sas.models.CylinderModel").CylinderModel model = CylinderModel() model.setParam("radius", radius) model.setParam("length", length) ff = cf.SASCF("cylinder", model) - r1 = numpy.arange(0, 10, 0.1, dtype = float) - r2 = numpy.arange(0, 50, 0.1, dtype = float) - r3 = numpy.arange(0, 100, 0.1, dtype = float) - r4 = numpy.arange(0, 500, 0.1, dtype = float) + r1 = numpy.arange(0, 10, 0.1, dtype=float) + r2 = numpy.arange(0, 50, 0.1, dtype=float) + r3 = numpy.arange(0, 100, 0.1, dtype=float) + r4 = numpy.arange(0, 500, 0.1, dtype=float) fr1 = ff(r1) fr2 = ff(r2) @@ -120,36 +118,37 @@ def testCylinder(self): fr4 = ff(r4) d = fr1 - numpy.interp(r1, r2, fr2) - res12 = numpy.dot(d,d) + res12 = numpy.dot(d, d) res12 /= numpy.dot(fr1, fr1) self.assertAlmostEqual(0, res12, 4) d = fr1 - numpy.interp(r1, r3, fr3) - res13 = numpy.dot(d,d) + res13 = numpy.dot(d, d) res13 /= numpy.dot(fr1, fr1) self.assertAlmostEqual(0, res13, 4) d = fr1 - numpy.interp(r1, r4, fr4) - res14 = numpy.dot(d,d) + res14 = numpy.dot(d, d) res14 /= numpy.dot(fr1, fr1) self.assertAlmostEqual(0, res14, 4) d = fr2 - numpy.interp(r2, r3, fr3) - res23 = numpy.dot(d,d) + res23 = numpy.dot(d, d) res23 /= numpy.dot(fr2, fr2) self.assertAlmostEqual(0, res23, 4) d = fr2 - numpy.interp(r2, r4, fr4) - res24 = numpy.dot(d,d) + res24 = numpy.dot(d, d) res24 /= numpy.dot(fr2, fr2) self.assertAlmostEqual(0, res24, 4) d = fr3 - numpy.interp(r3, r4, fr4) - res34 = numpy.dot(d,d) + res34 = numpy.dot(d, d) res34 /= numpy.dot(fr3, fr3) self.assertAlmostEqual(0, res34, 4) return + # End of class TestSASCF if __name__ == "__main__": diff --git a/src/diffpy/srfit/tests/testconstraint.py b/src/diffpy/srfit/tests/testconstraint.py index c2501f14..57440096 100644 --- a/src/diffpy/srfit/tests/testconstraint.py +++ b/src/diffpy/srfit/tests/testconstraint.py @@ -17,10 +17,10 @@ import unittest +from diffpy.srfit.equation.builder import EquationFactory from diffpy.srfit.fitbase.constraint import Constraint -from diffpy.srfit.fitbase.recipeorganizer import equationFromString from diffpy.srfit.fitbase.parameter import Parameter -from diffpy.srfit.equation.builder import EquationFactory +from diffpy.srfit.fitbase.recipeorganizer import equationFromString class TestConstraint(unittest.TestCase): diff --git a/src/diffpy/srfit/tests/testcontribution.py b/src/diffpy/srfit/tests/testcontribution.py index c28e9958..7e0eb8fd 100644 --- a/src/diffpy/srfit/tests/testcontribution.py +++ b/src/diffpy/srfit/tests/testcontribution.py @@ -17,13 +17,13 @@ import unittest -from numpy import arange, dot, array_equal, sin +from numpy import arange, array_equal, dot, sin +from diffpy.srfit.exceptions import SrFitError from diffpy.srfit.fitbase.fitcontribution import FitContribution -from diffpy.srfit.fitbase.profilegenerator import ProfileGenerator -from diffpy.srfit.fitbase.profile import Profile from diffpy.srfit.fitbase.parameter import Parameter -from diffpy.srfit.exceptions import SrFitError +from diffpy.srfit.fitbase.profile import Profile +from diffpy.srfit.fitbase.profilegenerator import ProfileGenerator from diffpy.srfit.tests.utils import noObserversInGlobalBuilders @@ -47,16 +47,15 @@ def testSetProfile(self): self.assertTrue(fc._eq is None) self.assertTrue(fc._reseq is None) # check type checking - fc1 = FitContribution('test1') - self.assertRaises(TypeError, fc1.setProfile, 'invalid') + fc1 = FitContribution("test1") + self.assertRaises(TypeError, fc1.setProfile, "invalid") # check if residual equation is set up when possible - fc2 = FitContribution('test2') - fc2.setEquation('A * x') + fc2 = FitContribution("test2") + fc2.setEquation("A * x") fc2.setProfile(profile) self.assertFalse(fc2._reseq is None) return - def testAddProfileGenerator(self): fc = self.fitcontribution gen = self.gen @@ -115,7 +114,7 @@ def testReplacements(self): profile = self.profile profile.setObservedProfile(xobs, yobs) xobs2 = arange(0, 10, 0.8) - yobs2 = 0.5*xobs2 + yobs2 = 0.5 * xobs2 profile2 = Profile() profile2.setObservedProfile(xobs2, yobs2) gen = self.gen @@ -145,7 +144,6 @@ def testReplacements(self): self.assertEqual(len(xobs2), len(fc.residual())) return - def testResidual(self): """Test the residual, which requires all other methods.""" fc = self.fitcontribution @@ -195,7 +193,7 @@ def testResidual(self): self.assertTrue(fc._eq._value is None) self.assertTrue(fc._reseq._value is None) xobs = arange(0, 10, 0.5) - yobs = 9*sin(xobs) + yobs = 9 * sin(xobs) profile.setObservedProfile(xobs, yobs) self.assertTrue(fc._eq._value is None) self.assertTrue(fc._reseq._value is None) @@ -207,25 +205,23 @@ def testResidual(self): fc.setEquation("2*I") fc.setResidualEquation("resv") chiv = fc.residual() - self.assertAlmostEqual(sum((2*xobs-yobs)**2)/sum(yobs**2), - dot(chiv, chiv)) + self.assertAlmostEqual(sum((2 * xobs - yobs) ** 2) / sum(yobs**2), dot(chiv, chiv)) # Make a custom residual. fc.setResidualEquation("abs(eq-y)**0.5") chiv = fc.residual() - self.assertAlmostEqual(sum(abs(2*xobs-yobs)), dot(chiv, chiv)) + self.assertAlmostEqual(sum(abs(2 * xobs - yobs)), dot(chiv, chiv)) # Test configuration checks - fc1 = FitContribution('test1') - self.assertRaises(SrFitError, fc1.setResidualEquation, 'chiv') + fc1 = FitContribution("test1") + self.assertRaises(SrFitError, fc1.setResidualEquation, "chiv") fc1.setProfile(self.profile) - self.assertRaises(SrFitError, fc1.setResidualEquation, 'chiv') - fc1.setEquation('A * x') - fc1.setResidualEquation('chiv') + self.assertRaises(SrFitError, fc1.setResidualEquation, "chiv") + fc1.setEquation("A * x") + fc1.setResidualEquation("chiv") self.assertTrue(noObserversInGlobalBuilders()) return - def test_setEquation(self): """Check replacement of removed parameters.""" fc = self.fitcontribution @@ -234,61 +230,55 @@ def test_setEquation(self): self.assertEqual(7, fc.evaluate()) fc.removeParameter(fc.x) x = arange(0, 10, 0.5) - fc.newParameter('x', x) + fc.newParameter("x", x) self.assertTrue(array_equal(5 + x, fc.evaluate())) self.assertTrue(noObserversInGlobalBuilders()) return - def test_getEquation(self): """Check getting the current profile simulation formula.""" fc = self.fitcontribution - self.assertEqual('', fc.getEquation()) + self.assertEqual("", fc.getEquation()) fc.setEquation("A * sin(x + 5)") - self.assertEqual('(A * sin((x + 5)))', fc.getEquation()) + self.assertEqual("(A * sin((x + 5)))", fc.getEquation()) self.assertTrue(noObserversInGlobalBuilders()) return - def test_getResidualEquation(self): """Check getting the current formula for residual equation.""" fc = self.fitcontribution - self.assertEqual('', fc.getResidualEquation()) + self.assertEqual("", fc.getResidualEquation()) fc.setProfile(self.profile) - fc.setEquation('A * x + B') - self.assertEqual('((eq - y) / dy)', fc.getResidualEquation()) - fc.setResidualEquation('2 * (eq - y)') - self.assertEqual('(2 * (eq - y))', fc.getResidualEquation()) + fc.setEquation("A * x + B") + self.assertEqual("((eq - y) / dy)", fc.getResidualEquation()) + fc.setResidualEquation("2 * (eq - y)") + self.assertEqual("(2 * (eq - y))", fc.getResidualEquation()) return - def test_releaseOldEquations(self): - """Ensure EquationFactory does not hold to obsolete Equations. - """ + """Ensure EquationFactory does not hold to obsolete Equations.""" fc = self.fitcontribution self.assertEqual(0, len(fc._eqfactory.equations)) for i in range(5): - fc.setEquation('A * x + B') + fc.setEquation("A * x + B") self.assertEqual(1, len(fc._eqfactory.equations)) fc.setProfile(self.profile) for i in range(5): - fc.setResidualEquation('chiv') + fc.setResidualEquation("chiv") self.assertEqual(2, len(fc._eqfactory.equations)) return - def test_registerFunction(self): - """Ensure registered function works after second setEquation call. - """ + """Ensure registered function works after second setEquation call.""" fc = self.fitcontribution - fsquare = lambda x : x**2 - fc.registerFunction(fsquare, name='fsquare') - fc.setEquation('fsquare') + fsquare = lambda x: x**2 + fc.registerFunction(fsquare, name="fsquare") + fc.setEquation("fsquare") fc.x.setValue(5) self.assertEqual(25, fc.evaluate()) fc.x << 6 self.assertEqual(36, fc.evaluate()) - fc.setEquation('fsquare + 5') + fc.setEquation("fsquare + 5") self.assertEqual(41, fc.evaluate()) fc.x << -1 self.assertEqual(6, fc.evaluate()) diff --git a/src/diffpy/srfit/tests/testdiffpyparset.py b/src/diffpy/srfit/tests/testdiffpyparset.py index fb9a2990..b423ff13 100644 --- a/src/diffpy/srfit/tests/testdiffpyparset.py +++ b/src/diffpy/srfit/tests/testdiffpyparset.py @@ -15,36 +15,37 @@ """Tests for diffpy.srfit.structure package.""" -import unittest import pickle +import unittest import numpy -from diffpy.srfit.tests.utils import has_structure, _msg_nostructure +from diffpy.srfit.tests.utils import _msg_nostructure, has_structure # Global variables to be assigned in setUp Atom = Lattice = Structure = DiffpyStructureParSet = None # ---------------------------------------------------------------------------- + @unittest.skipUnless(has_structure, _msg_nostructure) class TestParameterAdapter(unittest.TestCase): def setUp(self): global Atom, Lattice, Structure, DiffpyStructureParSet - from diffpy.structure import Atom, Lattice, Structure from diffpy.srfit.structure.diffpyparset import DiffpyStructureParSet - return + from diffpy.structure import Atom, Lattice, Structure + return def testDiffpyStructureParSet(self): """Test the structure conversion.""" - a1 = Atom("Cu", xyz = numpy.array([.0, .1, .2]), Uisoequiv = 0.003) - a2 = Atom("Ag", xyz = numpy.array([.3, .4, .5]), Uisoequiv = 0.002) + a1 = Atom("Cu", xyz=numpy.array([0.0, 0.1, 0.2]), Uisoequiv=0.003) + a2 = Atom("Ag", xyz=numpy.array([0.3, 0.4, 0.5]), Uisoequiv=0.002) l = Lattice(2.5, 2.5, 2.5, 90, 90, 90) - dsstru = Structure([a1,a2], l) + dsstru = Structure([a1, a2], l) # Structure makes copies a1 = dsstru[0] a2 = dsstru[1] @@ -63,14 +64,14 @@ def _testAtoms(): self.assertEqual(a2.Bisoequiv, s.Ag0.Biso.getValue()) for i in range(1, 4): for j in range(i, 4): - uijstru = getattr(a1, "U%i%i"%(i,j)) - uij = getattr(s.Cu0, "U%i%i"%(i,j)).getValue() - uji = getattr(s.Cu0, "U%i%i"%(j,i)).getValue() + uijstru = getattr(a1, "U%i%i" % (i, j)) + uij = getattr(s.Cu0, "U%i%i" % (i, j)).getValue() + uji = getattr(s.Cu0, "U%i%i" % (j, i)).getValue() self.assertEqual(uijstru, uij) self.assertEqual(uijstru, uji) - bijstru = getattr(a1, "B%i%i"%(i,j)) - bij = getattr(s.Cu0, "B%i%i"%(i,j)).getValue() - bji = getattr(s.Cu0, "B%i%i"%(j,i)).getValue() + bijstru = getattr(a1, "B%i%i" % (i, j)) + bij = getattr(s.Cu0, "B%i%i" % (i, j)).getValue() + bji = getattr(s.Cu0, "B%i%i" % (j, i)).getValue() self.assertEqual(bijstru, bij) self.assertEqual(bijstru, bji) @@ -79,7 +80,6 @@ def _testAtoms(): self.assertEqual(a1.xyz[2], s.Cu0.z.getValue()) return - def _testLattice(): # Test the lattice @@ -114,10 +114,8 @@ def _testLattice(): self.assertNotEqual(d, dsstru.lattice.dist(a1.xyz, a2.xyz)) return - def test___repr__(self): - """Test representation of DiffpyStructureParSet objects. - """ + """Test representation of DiffpyStructureParSet objects.""" lat = Lattice(3, 3, 2, 90, 90, 90) atom = Atom("C", [0, 0.2, 0.5]) stru = Structure([atom], lattice=lat) @@ -127,10 +125,8 @@ def test___repr__(self): self.assertEqual(repr(atom), repr(dsps.atoms[0])) return - def test_pickling(self): - """Test pickling of DiffpyStructureParSet. - """ + """Test pickling of DiffpyStructureParSet.""" stru = Structure([Atom("C", [0, 0.2, 0.5])]) dsps = DiffpyStructureParSet("dsps", stru) data = pickle.dumps(dsps) @@ -139,6 +135,7 @@ def test_pickling(self): self.assertEqual(0.2, dsps2.atoms[0].y.value) return + # End of class TestParameterAdapter if __name__ == "__main__": diff --git a/src/diffpy/srfit/tests/testequation.py b/src/diffpy/srfit/tests/testequation.py index 34b79361..8d264451 100644 --- a/src/diffpy/srfit/tests/testequation.py +++ b/src/diffpy/srfit/tests/testequation.py @@ -19,8 +19,7 @@ import diffpy.srfit.equation.literals as literals from diffpy.srfit.equation import Equation -from diffpy.srfit.tests.utils import _makeArgs -from diffpy.srfit.tests.utils import noObserversInGlobalBuilders +from diffpy.srfit.tests.utils import _makeArgs, noObserversInGlobalBuilders class TestEquation(unittest.TestCase): @@ -74,18 +73,18 @@ def testSimpleFunction(self): self.assertTrue(v3 is eq.v3) self.assertTrue(v4 is eq.v4) - self.assertEqual(20, eq()) # 20 = 2.5*(1+3)*(4-2) - self.assertEqual(20, eq.getValue()) # same as above - self.assertEqual(20, eq.value) # same as above - self.assertEqual(25, eq(v1=2)) # 25 = 2.5*(2+3)*(4-2) - self.assertEqual(50, eq(v2=0)) # 50 = 2.5*(2+3)*(4-0) - self.assertEqual(30, eq(v3=1)) # 30 = 2.5*(2+1)*(4-0) - self.assertEqual(0, eq(v4=0)) # 20 = 2.5*(2+1)*(0-0) + self.assertEqual(20, eq()) # 20 = 2.5*(1+3)*(4-2) + self.assertEqual(20, eq.getValue()) # same as above + self.assertEqual(20, eq.value) # same as above + self.assertEqual(25, eq(v1=2)) # 25 = 2.5*(2+3)*(4-2) + self.assertEqual(50, eq(v2=0)) # 50 = 2.5*(2+3)*(4-0) + self.assertEqual(30, eq(v3=1)) # 30 = 2.5*(2+1)*(4-0) + self.assertEqual(0, eq(v4=0)) # 20 = 2.5*(2+1)*(0-0) # Try some swapping eq.swap(v4, v1) self.assertTrue(eq._value is None) - self.assertEqual(15, eq()) # 15 = 2.5*(2+1)*(2-0) + self.assertEqual(15, eq()) # 15 = 2.5*(2+1)*(2-0) args = eq.args self.assertTrue(v4 not in args) @@ -160,18 +159,18 @@ def testEmbeddedEquation(self): self.assertTrue(eq._value is None) v1.value = 1 - self.assertEqual(20, eq()) # 20 = 2.5*(1+3)*(4-2) - self.assertEqual(20, eq.getValue()) # same as above - self.assertEqual(20, eq.value) # same as above - self.assertEqual(25, eq(v1=2)) # 25 = 2.5*(2+3)*(4-2) - self.assertEqual(50, eq(v2=0)) # 50 = 2.5*(2+3)*(4-0) - self.assertEqual(30, eq(v3=1)) # 30 = 2.5*(2+1)*(4-0) - self.assertEqual(0, eq(v4=0)) # 20 = 2.5*(2+1)*(0-0) + self.assertEqual(20, eq()) # 20 = 2.5*(1+3)*(4-2) + self.assertEqual(20, eq.getValue()) # same as above + self.assertEqual(20, eq.value) # same as above + self.assertEqual(25, eq(v1=2)) # 25 = 2.5*(2+3)*(4-2) + self.assertEqual(50, eq(v2=0)) # 50 = 2.5*(2+3)*(4-0) + self.assertEqual(30, eq(v3=1)) # 30 = 2.5*(2+1)*(4-0) + self.assertEqual(0, eq(v4=0)) # 20 = 2.5*(2+1)*(0-0) # Try some swapping. eq.swap(v4, v1) self.assertTrue(eq._value is None) - self.assertEqual(15, eq()) # 15 = 2.5*(2+1)*(2-0) + self.assertEqual(15, eq()) # 15 = 2.5*(2+1)*(2-0) args = eq.args self.assertTrue(v4 not in args) diff --git a/src/diffpy/srfit/tests/testfitrecipe.py b/src/diffpy/srfit/tests/testfitrecipe.py index 3df264e9..11645991 100644 --- a/src/diffpy/srfit/tests/testfitrecipe.py +++ b/src/diffpy/srfit/tests/testfitrecipe.py @@ -17,12 +17,12 @@ import unittest -from numpy import linspace, array_equal, pi, sin, dot +from numpy import array_equal, dot, linspace, pi, sin -from diffpy.srfit.fitbase.fitrecipe import FitRecipe from diffpy.srfit.fitbase.fitcontribution import FitContribution -from diffpy.srfit.fitbase.profile import Profile +from diffpy.srfit.fitbase.fitrecipe import FitRecipe from diffpy.srfit.fitbase.parameter import Parameter +from diffpy.srfit.fitbase.profile import Profile from diffpy.srfit.tests.utils import capturestdout @@ -53,8 +53,8 @@ def testFixFree(self): recipe = self.recipe con = self.fitcontribution - recipe.addVar(con.A, 2, tag = "tagA") - recipe.addVar(con.k, 1, tag = "tagk") + recipe.addVar(con.A, 2, tag="tagA") + recipe.addVar(con.k, 1, tag="tagk") recipe.addVar(con.c, 0) recipe.newVar("B", 0) @@ -78,7 +78,7 @@ def testFixFree(self): self.assertTrue(recipe.isFree(recipe.k)) self.assertTrue(recipe.isFree(recipe.c)) self.assertTrue(recipe.isFree(recipe.B)) - recipe.fix(recipe.A, "tagk", c = 3) + recipe.fix(recipe.A, "tagk", c=3) self.assertFalse(recipe.isFree(recipe.A)) self.assertFalse(recipe.isFree(recipe.k)) self.assertFalse(recipe.isFree(recipe.c)) @@ -91,7 +91,7 @@ def testFixFree(self): self.assertFalse(recipe.isFree(recipe.B)) self.assertRaises(ValueError, recipe.free, "junk") - self.assertRaises(ValueError, recipe.fix, tagA = 1) + self.assertRaises(ValueError, recipe.fix, tagA=1) self.assertRaises(ValueError, recipe.fix, "junk") return @@ -143,7 +143,6 @@ def testVars(self): self.assertTrue(2 in values) return - def testResidual(self): """Test the residual and everything that can change it.""" @@ -153,16 +152,15 @@ def testResidual(self): # Change the c value to 1 so that the equation evaluates as sin(x+1) x = self.profile.x - y = sin(x+1) + y = sin(x + 1) self.recipe.cont.c.setValue(1) res = self.recipe.residual() - self.assertTrue( array_equal(y-self.profile.y, res) ) + self.assertTrue(array_equal(y - self.profile.y, res)) # Try some constraints # Make c = 2*A, A = Avar var = self.recipe.newVar("Avar") - self.recipe.constrain(self.fitcontribution.c, "2*A", - {"A" : self.fitcontribution.A}) + self.recipe.constrain(self.fitcontribution.c, "2*A", {"A": self.fitcontribution.A}) self.assertEqual(2, self.fitcontribution.c.value) self.recipe.constrain(self.fitcontribution.A, var) self.assertEqual(1, var.getValue()) @@ -171,9 +169,9 @@ def testResidual(self): self.assertEqual(2, self.fitcontribution.c.value) # The equation should evaluate to sin(x+2) x = self.profile.x - y = sin(x+2) + y = sin(x + 2) res = self.recipe.residual() - self.assertTrue( array_equal(y-self.profile.y, res) ) + self.assertTrue(array_equal(y - self.profile.y, res)) # Now try some restraints. We want c to be exactly zero. It should give # a penalty of (c-0)**2, which is 4 in this case @@ -181,7 +179,7 @@ def testResidual(self): self.recipe._ready = False res = self.recipe.residual() chi2 = 4 + dot(y - self.profile.y, y - self.profile.y) - self.assertAlmostEqual(chi2, dot(res, res) ) + self.assertAlmostEqual(chi2, dot(res, res)) # Clear the constraint and restore the value of c to 0. This should # give us chi2 = 0 again. @@ -189,7 +187,7 @@ def testResidual(self): self.fitcontribution.c.setValue(0) res = self.recipe.residual([self.recipe.cont.A.getValue()]) chi2 = 0 - self.assertAlmostEqual(chi2, dot(res, res) ) + self.assertAlmostEqual(chi2, dot(res, res)) # Remove the restraint and variable self.recipe.unrestrain(r1) @@ -197,15 +195,15 @@ def testResidual(self): self.recipe._ready = False res = self.recipe.residual() chi2 = 0 - self.assertAlmostEqual(chi2, dot(res, res) ) + self.assertAlmostEqual(chi2, dot(res, res)) # Add constraints at the fitcontribution level. self.fitcontribution.constrain(self.fitcontribution.c, "2*A") # This should evaluate to sin(x+2) x = self.profile.x - y = sin(x+2) + y = sin(x + 2) res = self.recipe.residual() - self.assertTrue( array_equal(y-self.profile.y, res) ) + self.assertTrue(array_equal(y - self.profile.y, res)) # Add a restraint at the fitcontribution level. r1 = self.fitcontribution.restrain(self.fitcontribution.c, 0, 0, 1) @@ -213,9 +211,9 @@ def testResidual(self): # The chi2 is the same as above, plus 4 res = self.recipe.residual() x = self.profile.x - y = sin(x+2) + y = sin(x + 2) chi2 = 4 + dot(y - self.profile.y, y - self.profile.y) - self.assertAlmostEqual(chi2, dot(res, res) ) + self.assertAlmostEqual(chi2, dot(res, res)) # Remove those self.fitcontribution.unrestrain(r1) @@ -224,7 +222,7 @@ def testResidual(self): self.fitcontribution.c.setValue(0) res = self.recipe.residual() chi2 = 0 - self.assertAlmostEqual(chi2, dot(res, res) ) + self.assertAlmostEqual(chi2, dot(res, res)) # Now try to use the observed profile inside of the equation # Set the equation equal to the data @@ -239,29 +237,29 @@ def testResidual(self): return - def testPrintFitHook(self): "check output from default PrintFitHook." self.recipe.addVar(self.fitcontribution.c) - self.recipe.restrain('c', lb=5) - pfh, = self.recipe.getFitHooks() + self.recipe.restrain("c", lb=5) + (pfh,) = self.recipe.getFitHooks() out = capturestdout(self.recipe.scalarResidual) - self.assertEqual('', out) + self.assertEqual("", out) pfh.verbose = 1 out = capturestdout(self.recipe.scalarResidual) self.assertTrue(out.strip().isdigit()) - self.assertFalse('\nRestraints:' in out) + self.assertFalse("\nRestraints:" in out) pfh.verbose = 2 out = capturestdout(self.recipe.scalarResidual) - self.assertTrue('\nResidual:' in out) - self.assertTrue('\nRestraints:' in out) - self.assertFalse('\nVariables' in out) + self.assertTrue("\nResidual:" in out) + self.assertTrue("\nRestraints:" in out) + self.assertFalse("\nVariables" in out) pfh.verbose = 3 out = capturestdout(self.recipe.scalarResidual) - self.assertTrue('\nVariables' in out) - self.assertTrue('c = ' in out) + self.assertTrue("\nVariables" in out) + self.assertTrue("c = " in out) return + # End of class TestFitRecipe # ---------------------------------------------------------------------------- diff --git a/src/diffpy/srfit/tests/testfitresults.py b/src/diffpy/srfit/tests/testfitresults.py index c5d6c9cc..18d65435 100644 --- a/src/diffpy/srfit/tests/testfitresults.py +++ b/src/diffpy/srfit/tests/testfitresults.py @@ -33,7 +33,7 @@ def setUp(self): self.Aval = 5.77619823e-01 self.sigval = -9.22758690e-01 - self.x0val = 6.12422115e+00 + self.x0val = 6.12422115e00 return def testInitializeFromFileName(self): @@ -52,7 +52,7 @@ def testInitializeFromFileObj(self): self.assertEqual(0, recipe.A.value) self.assertEqual(0, recipe.sig.value) self.assertEqual(0, recipe.x0.value) - infile = open(self.filename, 'r') + infile = open(self.filename, "r") initializeRecipe(recipe, infile) self.assertFalse(infile.closed) infile.close() @@ -61,13 +61,12 @@ def testInitializeFromFileObj(self): self.assertAlmostEqual(self.x0val, recipe.x0.value) return - def testInitializeFromString(self): recipe = self.recipe self.assertEqual(0, recipe.A.value) self.assertEqual(0, recipe.sig.value) self.assertEqual(0, recipe.x0.value) - infile = open(self.filename, 'r') + infile = open(self.filename, "r") resstr = infile.read() infile.close() initializeRecipe(recipe, resstr) @@ -76,6 +75,7 @@ def testInitializeFromString(self): self.assertAlmostEqual(self.x0val, recipe.x0.value) return + if __name__ == "__main__": unittest.main() diff --git a/src/diffpy/srfit/tests/testliterals.py b/src/diffpy/srfit/tests/testliterals.py index 7667be3e..99c1aa24 100644 --- a/src/diffpy/srfit/tests/testliterals.py +++ b/src/diffpy/srfit/tests/testliterals.py @@ -24,6 +24,7 @@ # ---------------------------------------------------------------------------- + class TestArgument(unittest.TestCase): def testInit(self): @@ -34,7 +35,6 @@ def testInit(self): self.assertTrue(None is a.name) return - def testIdentity(self): """Make sure an Argument is an Argument.""" a = literals.Argument() @@ -42,7 +42,6 @@ def testIdentity(self): self.assertTrue(isinstance(a, abcs.ArgumentABC)) return - def testValue(self): """Test value setting.""" @@ -59,16 +58,16 @@ def testValue(self): self.assertAlmostEqual(3.14, a.getValue()) return + # ---------------------------------------------------------------------------- + class TestCustomOperator(unittest.TestCase): def setUp(self): - self.op = literals.makeOperator( - name="add", symbol="+", operation=numpy.add, nin=2, nout=1) + self.op = literals.makeOperator(name="add", symbol="+", operation=numpy.add, nin=2, nout=1) return - def testInit(self): """Test that everthing initializes as expected.""" op = self.op @@ -80,7 +79,6 @@ def testInit(self): self.assertEqual([], op.args) return - def testIdentity(self): """Make sure an Argument is an Argument.""" op = self.op @@ -88,13 +86,12 @@ def testIdentity(self): self.assertTrue(isinstance(op, abcs.OperatorABC)) return - def testValue(self): """Test value.""" # Test addition and operations op = self.op - a = literals.Argument(value = 0) - b = literals.Argument(value = 0) + a = literals.Argument(value=0) + b = literals.Argument(value=0) op.addLiteral(a) op.addLiteral(b) @@ -113,7 +110,6 @@ def testValue(self): return - def testAddLiteral(self): """Test adding a literal to an operator node.""" op = self.op @@ -123,8 +119,8 @@ def testAddLiteral(self): self.assertEqual(op.getValue(), 1) # Test addition and operations - a = literals.Argument(name = "a", value = 0) - b = literals.Argument(name = "b", value = 0) + a = literals.Argument(name="a", value=0) + b = literals.Argument(name="b", value=0) op.addLiteral(a) self.assertRaises(ValueError, op.getValue) @@ -140,21 +136,21 @@ def testAddLiteral(self): # Test for self-references # Try to add self - op1 = literals.makeOperator(name="add", symbol="+", - operation=numpy.add, nin=2, nout=1) + op1 = literals.makeOperator(name="add", symbol="+", operation=numpy.add, nin=2, nout=1) op1.addLiteral(a) self.assertRaises(ValueError, op1.addLiteral, op1) # Try to add argument that contains self - op2 = literals.makeOperator( - name="sub", symbol="-", operation=numpy.subtract, nin=2, nout=1) + op2 = literals.makeOperator(name="sub", symbol="-", operation=numpy.subtract, nin=2, nout=1) op2.addLiteral(op1) self.assertRaises(ValueError, op1.addLiteral, op2) return + # ---------------------------------------------------------------------------- + class TestConvolutionOperator(unittest.TestCase): def testValue(self): @@ -169,10 +165,10 @@ def testValue(self): mu2 = 2.5 sig2 = 0.4 - g1 = exp(-0.5*((x-mu1)/sig1)**2) - a1 = literals.Argument(name = "g1", value = g1) - g2 = exp(-0.5*((x-mu2)/sig2)**2) - a2 = literals.Argument(name = "g2", value = g2) + g1 = exp(-0.5 * ((x - mu1) / sig1) ** 2) + a1 = literals.Argument(name="g1", value=g1) + g2 = exp(-0.5 * ((x - mu2) / sig2) ** 2) + a2 = literals.Argument(name="g2", value=g2) op = literals.ConvolutionOperator() op.addLiteral(a1) @@ -181,24 +177,25 @@ def testValue(self): g3c = op.value mu3 = mu1 - sig3 = (sig1**2 + sig2**2)**0.5 - g3 = exp(-0.5*((x-mu3)/sig3)**2) - g3 *= sum(g1)/sum(g3) + sig3 = (sig1**2 + sig2**2) ** 0.5 + g3 = exp(-0.5 * ((x - mu3) / sig3) ** 2) + g3 *= sum(g1) / sum(g3) self.assertAlmostEqual(sum(g3c), sum(g3)) - self.assertAlmostEqual(0, sum((g3-g3c)**2)) + self.assertAlmostEqual(0, sum((g3 - g3c) ** 2)) return + # ---------------------------------------------------------------------------- + class TestArrayOperator(unittest.TestCase): def test_value(self): - """Check ArrayOperator.value. - """ - x = literals.Argument('x', 1.0) - y = literals.Argument('y', 2.0) - z = literals.Argument('z', 3.0) + """Check ArrayOperator.value.""" + x = literals.Argument("x", 1.0) + y = literals.Argument("y", 2.0) + z = literals.Argument("z", 3.0) # check empty array op = literals.ArrayOperator() self.assertEqual(0, len(op.value)) @@ -213,6 +210,7 @@ def test_value(self): self.assertTrue(numpy.array_equal([1, 2, 7], op.value)) return + # ---------------------------------------------------------------------------- if __name__ == "__main__": diff --git a/src/diffpy/srfit/tests/testobjcrystparset.py b/src/diffpy/srfit/tests/testobjcrystparset.py index 34cc2aa8..a3b236c0 100644 --- a/src/diffpy/srfit/tests/testobjcrystparset.py +++ b/src/diffpy/srfit/tests/testobjcrystparset.py @@ -19,7 +19,7 @@ import numpy -from diffpy.srfit.tests.utils import has_pyobjcryst, _msg_nopyobjcryst +from diffpy.srfit.tests.utils import _msg_nopyobjcryst, has_pyobjcryst # Global variables to be assigned in setUp ObjCrystCrystalParSet = spacegroups = None @@ -89,6 +89,7 @@ -2.279809890 -2.580456608 -0.724000000 """ + def makeC60(): """Make a crystal containing the C60 molecule using pyobjcryst.""" pi = numpy.pi @@ -99,28 +100,32 @@ def makeC60(): c.AddScatterer(m) sp = ScatteringPowerAtom("C", "C") - sp.SetBiso(8*pi*pi*0.003) - #c.AddScatteringPower(sp) + sp.SetBiso(8 * pi * pi * 0.003) + # c.AddScatteringPower(sp) for i, l in enumerate(c60xyz.strip().splitlines()): x, y, z = map(float, l.split()) - m.AddAtom(x, y, z, sp, "C%i"%i) + m.AddAtom(x, y, z, sp, "C%i" % i) return c + # ---------------------------------------------------------------------------- + @unittest.skipUnless(has_pyobjcryst, _msg_nopyobjcryst) class TestParameterAdapter(unittest.TestCase): def setUp(self): global ObjCrystCrystalParSet, Crystal, Atom, Molecule global ScatteringPowerAtom - from diffpy.srfit.structure.objcrystparset import ObjCrystCrystalParSet - from pyobjcryst.crystal import Crystal from pyobjcryst.atom import Atom + from pyobjcryst.crystal import Crystal from pyobjcryst.molecule import Molecule from pyobjcryst.scatteringpower import ScatteringPowerAtom + + from diffpy.srfit.structure.objcrystparset import ObjCrystCrystalParSet + self.occryst = makeC60() self.ocmol = self.occryst.GetScatterer("c60") return @@ -130,7 +135,6 @@ def tearDown(self): del self.ocmol return - def testObjCrystParSet(self): """Test the structure conversion.""" @@ -181,7 +185,6 @@ def _testMolecule(): self.assertAlmostEqual(ocsp.Biso, a.Biso.getValue()) return - _testCrystal() _testMolecule() @@ -196,17 +199,16 @@ def _testMolecule(): _testMolecule() ## Now change values from the srfit StructureParSet - cryst.c60.C44.x.setValue( 1.1 ) - cryst.c60.C44.occ.setValue( 1.1 ) - cryst.c60.C44.Biso.setValue( 1.1 ) - cryst.c60.q3.setValue( 1.1 ) + cryst.c60.C44.x.setValue(1.1) + cryst.c60.C44.occ.setValue(1.1) + cryst.c60.C44.Biso.setValue(1.1) + cryst.c60.q3.setValue(1.1) cryst.a.setValue(1.1) _testCrystal() _testMolecule() return - def testImplicitBondLengthRestraints(self): """Test the structure with implicit bond lengths.""" occryst = self.occryst @@ -233,7 +235,6 @@ def testImplicitBondLengthRestraints(self): return - def testImplicitBondAngleRestraints(self): """Test the structure with implicit bond angles.""" occryst = self.occryst @@ -260,17 +261,14 @@ def testImplicitBondAngleRestraints(self): return - def testImplicitDihedralAngleRestraints(self): """Test the structure with implicit dihedral angles.""" occryst = self.occryst ocmol = self.ocmol # Add some bond angles to the molecule - ocmol.AddDihedralAngle(ocmol[0], ocmol[5], ocmol[8], ocmol[41], 1.1, - 0.1, 0.1) - ocmol.AddDihedralAngle(ocmol[0], ocmol[7], ocmol[44], ocmol[2], 1.3, - 0.1, 0.1) + ocmol.AddDihedralAngle(ocmol[0], ocmol[5], ocmol[8], ocmol[41], 1.1, 0.1, 0.1) + ocmol.AddDihedralAngle(ocmol[0], ocmol[7], ocmol[44], ocmol[2], 1.3, 0.1, 0.1) # make our crystal cryst = ObjCrystCrystalParSet("bucky", occryst) @@ -289,13 +287,11 @@ def testImplicitDihedralAngleRestraints(self): return - def testImplicitStretchModes(self): """Test the molecule with implicit stretch modes.""" # Not sure how to make this happen. pass - def testExplicitBondLengthRestraints(self): """Test the structure with explicit bond lengths.""" occryst = self.occryst @@ -321,7 +317,6 @@ def testExplicitBondLengthRestraints(self): return - def testExplicitBondAngleRestraints(self): """Test the structure with explicit bond angles. @@ -337,10 +332,8 @@ def testExplicitBondAngleRestraints(self): m = cryst.c60 # restrain some bond angles - res0 = m.restrainBondAngle(m.atoms[0], m.atoms[5], m.atoms[8], 3.3, - 0.1, 0.1) - res1 = m.restrainBondAngle(m.atoms[0], m.atoms[7], m.atoms[44], 3.3, - 0.1, 0.1) + res0 = m.restrainBondAngle(m.atoms[0], m.atoms[5], m.atoms[8], 3.3, 0.1, 0.1) + res1 = m.restrainBondAngle(m.atoms[0], m.atoms[7], m.atoms[44], 3.3, 0.1, 0.1) # make sure that we have some restraints in the molecule self.assertTrue(2, len(m._restraints)) @@ -353,7 +346,6 @@ def testExplicitBondAngleRestraints(self): return - def testExplicitDihedralAngleRestraints(self): """Test the structure with explicit dihedral angles.""" occryst = self.occryst @@ -364,11 +356,8 @@ def testExplicitDihedralAngleRestraints(self): m = cryst.c60 # Restrain some dihedral angles. - res0 = m.restrainDihedralAngle(m.atoms[0], m.atoms[5], m.atoms[8], - m.atoms[41], 1.1, 0.1, 0.1) - res1 = m.restrainDihedralAngle(m.atoms[0], m.atoms[7], m.atoms[44], - m.atoms[2], 1.1, 0.1, 0.1) - + res0 = m.restrainDihedralAngle(m.atoms[0], m.atoms[5], m.atoms[8], m.atoms[41], 1.1, 0.1, 0.1) + res1 = m.restrainDihedralAngle(m.atoms[0], m.atoms[7], m.atoms[44], m.atoms[2], 1.1, 0.1, 0.1) # make sure that we have some restraints in the molecule self.assertTrue(2, len(m._restraints)) @@ -381,7 +370,6 @@ def testExplicitDihedralAngleRestraints(self): return - def testExplicitBondLengthParameter(self): """Test adding bond length parameters to the molecule.""" occryst = self.occryst @@ -401,48 +389,45 @@ def testExplicitBondLengthParameter(self): xyz0 = numpy.array([a0.x.getValue(), a0.y.getValue(), a0.z.getValue()]) xyz7 = numpy.array([a7.x.getValue(), a7.y.getValue(), a7.z.getValue()]) - xyz20 = numpy.array([a20.x.getValue(), a20.y.getValue(), - a20.z.getValue()]) + xyz20 = numpy.array([a20.x.getValue(), a20.y.getValue(), a20.z.getValue()]) dd = xyz0 - xyz7 - d0 = numpy.dot(dd, dd)**0.5 + d0 = numpy.dot(dd, dd) ** 0.5 self.assertAlmostEqual(d0, p1.getValue(), 6) # Record the unit direction of change for later - u = dd/d0 + u = dd / d0 # Change the value scale = 1.05 - p1.setValue(scale*d0) + p1.setValue(scale * d0) # Verify that it has changed. - self.assertAlmostEqual(scale*d0, p1.getValue()) + self.assertAlmostEqual(scale * d0, p1.getValue()) xyz0a = numpy.array([a0.x.getValue(), a0.y.getValue(), a0.z.getValue()]) xyz7a = numpy.array([a7.x.getValue(), a7.y.getValue(), a7.z.getValue()]) - xyz20a = numpy.array([a20.x.getValue(), a20.y.getValue(), - a20.z.getValue()]) + xyz20a = numpy.array([a20.x.getValue(), a20.y.getValue(), a20.z.getValue()]) dda = xyz0a - xyz7a - d1 = numpy.dot(dda, dda)**0.5 + d1 = numpy.dot(dda, dda) ** 0.5 - self.assertAlmostEqual(scale*d0, d1) + self.assertAlmostEqual(scale * d0, d1) # Verify that only the second and third atoms have moved. self.assertTrue(numpy.array_equal(xyz0, xyz0a)) - xyz7calc = xyz7 + (1-scale)*d0*u + xyz7calc = xyz7 + (1 - scale) * d0 * u for i in range(3): self.assertAlmostEqual(xyz7a[i], xyz7calc[i], 6) - xyz20calc = xyz20 + (1-scale)*d0*u + xyz20calc = xyz20 + (1 - scale) * d0 * u for i in range(3): self.assertAlmostEqual(xyz20a[i], xyz20calc[i], 6) return - def testExplicitBondAngleParameter(self): """Test adding bond angle parameters to the molecule.""" occryst = self.occryst @@ -458,18 +443,15 @@ def testExplicitBondAngleParameter(self): xyz0 = numpy.array([a0.x.getValue(), a0.y.getValue(), a0.z.getValue()]) xyz7 = numpy.array([a7.x.getValue(), a7.y.getValue(), a7.z.getValue()]) - xyz20 = numpy.array([a20.x.getValue(), a20.y.getValue(), - a20.z.getValue()]) - xyz25 = numpy.array([a25.x.getValue(), a25.y.getValue(), - a25.z.getValue()]) - + xyz20 = numpy.array([a20.x.getValue(), a20.y.getValue(), a20.z.getValue()]) + xyz25 = numpy.array([a25.x.getValue(), a25.y.getValue(), a25.z.getValue()]) v1 = xyz7 - xyz0 - d1 = numpy.dot(v1, v1)**0.5 + d1 = numpy.dot(v1, v1) ** 0.5 v2 = xyz7 - xyz20 - d2 = numpy.dot(v2, v2)**0.5 + d2 = numpy.dot(v2, v2) ** 0.5 - angle0 = numpy.arccos(numpy.dot(v1, v2)/(d1*d2)) + angle0 = numpy.arccos(numpy.dot(v1, v2) / (d1 * d2)) # Add a parameter p1 = m.addBondAngleParameter("C0720", a0, a7, a20) @@ -480,26 +462,24 @@ def testExplicitBondAngleParameter(self): # Change the value scale = 1.05 - p1.setValue(scale*angle0) + p1.setValue(scale * angle0) # Verify that it has changed. - self.assertAlmostEqual(scale*angle0, p1.getValue(), 6) + self.assertAlmostEqual(scale * angle0, p1.getValue(), 6) xyz0a = numpy.array([a0.x.getValue(), a0.y.getValue(), a0.z.getValue()]) xyz7a = numpy.array([a7.x.getValue(), a7.y.getValue(), a7.z.getValue()]) - xyz20a = numpy.array([a20.x.getValue(), a20.y.getValue(), - a20.z.getValue()]) - xyz25a = numpy.array([a25.x.getValue(), a25.y.getValue(), - a25.z.getValue()]) + xyz20a = numpy.array([a20.x.getValue(), a20.y.getValue(), a20.z.getValue()]) + xyz25a = numpy.array([a25.x.getValue(), a25.y.getValue(), a25.z.getValue()]) v1a = xyz7a - xyz0a - d1a = numpy.dot(v1a, v1a)**0.5 + d1a = numpy.dot(v1a, v1a) ** 0.5 v2a = xyz7a - xyz20a - d2a = numpy.dot(v2a, v2a)**0.5 + d2a = numpy.dot(v2a, v2a) ** 0.5 - angle1 = numpy.arccos(numpy.dot(v1a, v2a)/(d1a*d2a)) + angle1 = numpy.arccos(numpy.dot(v1a, v2a) / (d1a * d2a)) - self.assertAlmostEqual(scale*angle0, angle1) + self.assertAlmostEqual(scale * angle0, angle1) # Verify that only the last two atoms have moved. @@ -510,7 +490,6 @@ def testExplicitBondAngleParameter(self): return - def testExplicitDihedralAngleParameter(self): """Test adding dihedral angle parameters to the molecule.""" occryst = self.occryst @@ -527,13 +506,9 @@ def testExplicitDihedralAngleParameter(self): xyz0 = numpy.array([a0.x.getValue(), a0.y.getValue(), a0.z.getValue()]) xyz7 = numpy.array([a7.x.getValue(), a7.y.getValue(), a7.z.getValue()]) - xyz20 = numpy.array([a20.x.getValue(), a20.y.getValue(), - a20.z.getValue()]) - xyz25 = numpy.array([a25.x.getValue(), a25.y.getValue(), - a25.z.getValue()]) - xyz33 = numpy.array([a33.x.getValue(), a33.y.getValue(), - a33.z.getValue()]) - + xyz20 = numpy.array([a20.x.getValue(), a20.y.getValue(), a20.z.getValue()]) + xyz25 = numpy.array([a25.x.getValue(), a25.y.getValue(), a25.z.getValue()]) + xyz33 = numpy.array([a33.x.getValue(), a33.y.getValue(), a33.z.getValue()]) v12 = xyz0 - xyz7 v23 = xyz7 - xyz20 @@ -541,9 +516,9 @@ def testExplicitDihedralAngleParameter(self): v123 = numpy.cross(v12, v23) v234 = numpy.cross(v23, v34) - d123 = numpy.dot(v123, v123)**0.5 - d234 = numpy.dot(v234, v234)**0.5 - angle0 = -numpy.arccos(numpy.dot(v123, v234)/(d123*d234)) + d123 = numpy.dot(v123, v123) ** 0.5 + d234 = numpy.dot(v234, v234) ** 0.5 + angle0 = -numpy.arccos(numpy.dot(v123, v234) / (d123 * d234)) # Add a parameter p1 = m.addDihedralAngleParameter("C072025", a0, a7, a20, a25) @@ -554,19 +529,16 @@ def testExplicitDihedralAngleParameter(self): # Change the value scale = 1.05 - p1.setValue(scale*angle0) + p1.setValue(scale * angle0) # Verify that it has changed. - self.assertAlmostEqual(scale*angle0, p1.getValue(), 6) + self.assertAlmostEqual(scale * angle0, p1.getValue(), 6) xyz0a = numpy.array([a0.x.getValue(), a0.y.getValue(), a0.z.getValue()]) xyz7a = numpy.array([a7.x.getValue(), a7.y.getValue(), a7.z.getValue()]) - xyz20a = numpy.array([a20.x.getValue(), a20.y.getValue(), - a20.z.getValue()]) - xyz25a = numpy.array([a25.x.getValue(), a25.y.getValue(), - a25.z.getValue()]) - xyz33a = numpy.array([a33.x.getValue(), a33.y.getValue(), - a33.z.getValue()]) + xyz20a = numpy.array([a20.x.getValue(), a20.y.getValue(), a20.z.getValue()]) + xyz25a = numpy.array([a25.x.getValue(), a25.y.getValue(), a25.z.getValue()]) + xyz33a = numpy.array([a33.x.getValue(), a33.y.getValue(), a33.z.getValue()]) v12a = xyz0a - xyz7a v23a = xyz7a - xyz20a @@ -574,11 +546,11 @@ def testExplicitDihedralAngleParameter(self): v123a = numpy.cross(v12a, v23a) v234a = numpy.cross(v23a, v34a) - d123a = numpy.dot(v123a, v123a)**0.5 - d234a = numpy.dot(v234a, v234a)**0.5 - angle1 = -numpy.arccos(numpy.dot(v123a, v234a)/(d123a*d234a)) + d123a = numpy.dot(v123a, v123a) ** 0.5 + d234a = numpy.dot(v234a, v234a) ** 0.5 + angle1 = -numpy.arccos(numpy.dot(v123a, v234a) / (d123a * d234a)) - self.assertAlmostEqual(scale*angle0, angle1) + self.assertAlmostEqual(scale * angle0, angle1) # Verify that only the last two atoms have moved. @@ -590,10 +562,12 @@ def testExplicitDihedralAngleParameter(self): return + # End of class TestParameterAdapter # ---------------------------------------------------------------------------- + @unittest.skipUnless(has_pyobjcryst, _msg_nopyobjcryst) class TestCreateSpaceGroup(unittest.TestCase): """Test space group creation from pyobjcryst structures. @@ -612,6 +586,7 @@ def setUp(self): def getObjCrystParSetSpaceGroup(sg): """Make an ObjCrystCrystalParSet with the proper space group.""" from pyobjcryst.spacegroup import SpaceGroup + sgobjcryst = SpaceGroup(sg.short_name) sgnew = ObjCrystCrystalParSet._createSpaceGroup(sgobjcryst) return sgnew @@ -619,7 +594,7 @@ def getObjCrystParSetSpaceGroup(sg): @staticmethod def hashDiffPySpaceGroup(sg): lines = [str(sg.number % 1000)] + sorted(map(str, sg.iter_symops())) - s = '\n'.join(lines) + s = "\n".join(lines) return s def sgsEquivalent(self, sg1, sg2): @@ -640,7 +615,7 @@ def xtestCreateSpaceGroup(self): for smbls in sgtbx.space_group_symbol_iterator(): shn = smbls.hermann_mauguin() - short_name = shn.replace(' ', '') + short_name = shn.replace(" ", "") if spacegroups.IsSpaceGroupIdentifier(short_name): sg = spacegroups.GetSpaceGroup(shn) sgnew = self.getObjCrystParSetSpaceGroup(sg) @@ -648,6 +623,7 @@ def xtestCreateSpaceGroup(self): self.assertTrue(self.sgsEquivalent(sg, sgnew)) return + # End of class TestCreateSpaceGroup if __name__ == "__main__": diff --git a/src/diffpy/srfit/tests/testparameter.py b/src/diffpy/srfit/tests/testparameter.py index 76eaee3b..d3baea2c 100644 --- a/src/diffpy/srfit/tests/testparameter.py +++ b/src/diffpy/srfit/tests/testparameter.py @@ -17,8 +17,7 @@ import unittest -from diffpy.srfit.fitbase.parameter import Parameter -from diffpy.srfit.fitbase.parameter import ParameterAdapter, ParameterProxy +from diffpy.srfit.fitbase.parameter import Parameter, ParameterAdapter, ParameterProxy class TestParameter(unittest.TestCase): @@ -32,16 +31,17 @@ def testSetValue(self): # Try array import numpy + x = numpy.arange(0, 10, 0.1) l.setValue(x) - self.assertTrue( l.getValue() is x ) - self.assertTrue( l.value is x ) + self.assertTrue(l.getValue() is x) + self.assertTrue(l.value is x) # Change the array y = numpy.arange(0, 10, 0.5) l.value = y - self.assertTrue( l.getValue() is y ) - self.assertTrue( l.value is y ) + self.assertTrue(l.getValue() is y) + self.assertTrue(l.value is y) # Back to scalar l.setValue(1.01) @@ -49,6 +49,7 @@ def testSetValue(self): self.assertAlmostEqual(1.01, l.value) return + class TestParameterProxy(unittest.TestCase): def testProxy(self): @@ -73,6 +74,7 @@ def testProxy(self): return + class TestParameterAdapter(unittest.TestCase): def testWrapper(self): @@ -83,8 +85,7 @@ def testWrapper(self): l = Parameter("l", 3.14) # Try Accessor adaptation - la = ParameterAdapter("l", l, getter = Parameter.getValue, setter = - Parameter.setValue) + la = ParameterAdapter("l", l, getter=Parameter.getValue, setter=Parameter.setValue) self.assertEqual(l.name, la.name) self.assertEqual(l.getValue(), la.getValue()) @@ -98,7 +99,7 @@ def testWrapper(self): self.assertEqual(l.getValue(), la.getValue()) # Try Attribute adaptation - la = ParameterAdapter("l", l, attr = "value") + la = ParameterAdapter("l", l, attr="value") self.assertEqual(l.name, la.name) self.assertEqual("value", la.attr) diff --git a/src/diffpy/srfit/tests/testpdf.py b/src/diffpy/srfit/tests/testpdf.py index 426b7d81..793179c4 100644 --- a/src/diffpy/srfit/tests/testpdf.py +++ b/src/diffpy/srfit/tests/testpdf.py @@ -15,26 +15,24 @@ """Tests for pdf package.""" -import unittest -import pickle import io +import pickle +import unittest import numpy -from diffpy.srfit.tests.utils import datafile -from diffpy.srfit.tests.utils import has_srreal, _msg_nosrreal -from diffpy.srfit.tests.utils import has_structure, _msg_nostructure -from diffpy.srfit.pdf import PDFGenerator, PDFParser, PDFContribution from diffpy.srfit.exceptions import SrFitError +from diffpy.srfit.pdf import PDFContribution, PDFGenerator, PDFParser +from diffpy.srfit.tests.utils import _msg_nosrreal, _msg_nostructure, datafile, has_srreal, has_structure # ---------------------------------------------------------------------------- + class TestPDFParset(unittest.TestCase): def setUp(self): return - def testParser1(self): data = datafile("ni-q27r100-neutron.gr") parser = PDFParser() @@ -42,16 +40,16 @@ def testParser1(self): meta = parser._meta - self.assertEqual(data, meta['filename']) - self.assertEqual(1, meta['nbanks']) - self.assertEqual('N', meta['stype']) - self.assertEqual(27, meta['qmax']) - self.assertEqual(300, meta.get('temperature')) - self.assertEqual(None, meta.get('qdamp')) - self.assertEqual(None, meta.get('qbroad')) - self.assertEqual(None, meta.get('spdiameter')) - self.assertEqual(None, meta.get('scale')) - self.assertEqual(None, meta.get('doping')) + self.assertEqual(data, meta["filename"]) + self.assertEqual(1, meta["nbanks"]) + self.assertEqual("N", meta["stype"]) + self.assertEqual(27, meta["qmax"]) + self.assertEqual(300, meta.get("temperature")) + self.assertEqual(None, meta.get("qdamp")) + self.assertEqual(None, meta.get("qbroad")) + self.assertEqual(None, meta.get("spdiameter")) + self.assertEqual(None, meta.get("scale")) + self.assertEqual(None, meta.get("doping")) x, y, dx, dy = parser.getData() self.assertTrue(dx is None) @@ -62,15 +60,13 @@ def testParser1(self): res = numpy.dot(diff, diff) self.assertAlmostEqual(0, res) - testy = numpy.array([1.144, 2.258, 3.312, 4.279, 5.135, 5.862, 6.445, - 6.875, 7.150, 7.272]) + testy = numpy.array([1.144, 2.258, 3.312, 4.279, 5.135, 5.862, 6.445, 6.875, 7.150, 7.272]) diff = testy - y[:10] res = numpy.dot(diff, diff) self.assertAlmostEqual(0, res) return - def testParser2(self): data = datafile("si-q27r60-xray.gr") parser = PDFParser() @@ -78,16 +74,16 @@ def testParser2(self): meta = parser._meta - self.assertEqual(data, meta['filename']) - self.assertEqual(1, meta['nbanks']) - self.assertEqual('X', meta['stype']) - self.assertEqual(27, meta['qmax']) - self.assertEqual(300, meta.get('temperature')) - self.assertEqual(None, meta.get('qdamp')) - self.assertEqual(None, meta.get('qbroad')) - self.assertEqual(None, meta.get('spdiameter')) - self.assertEqual(None, meta.get('scale')) - self.assertEqual(None, meta.get('doping')) + self.assertEqual(data, meta["filename"]) + self.assertEqual(1, meta["nbanks"]) + self.assertEqual("X", meta["stype"]) + self.assertEqual(27, meta["qmax"]) + self.assertEqual(300, meta.get("temperature")) + self.assertEqual(None, meta.get("qdamp")) + self.assertEqual(None, meta.get("qbroad")) + self.assertEqual(None, meta.get("spdiameter")) + self.assertEqual(None, meta.get("scale")) + self.assertEqual(None, meta.get("doping")) x, y, dx, dy = parser.getData() testx = numpy.linspace(0.01, 60, 5999, endpoint=False) @@ -95,15 +91,38 @@ def testParser2(self): res = numpy.dot(diff, diff) self.assertAlmostEqual(0, res) - testy = numpy.array([0.1105784, 0.2199684, 0.3270088, 0.4305913, - 0.5296853, 0.6233606, 0.7108060, 0.7913456, 0.8644501, 0.9297440]) + testy = numpy.array( + [ + 0.1105784, + 0.2199684, + 0.3270088, + 0.4305913, + 0.5296853, + 0.6233606, + 0.7108060, + 0.7913456, + 0.8644501, + 0.9297440, + ] + ) diff = testy - y[:10] res = numpy.dot(diff, diff) self.assertAlmostEqual(0, res) - testdy = numpy.array([0.001802192, 0.003521449, 0.005079115, - 0.006404892, 0.007440527, 0.008142955, 0.008486813, 0.008466340, - 0.008096858, 0.007416456]) + testdy = numpy.array( + [ + 0.001802192, + 0.003521449, + 0.005079115, + 0.006404892, + 0.007440527, + 0.008142955, + 0.008486813, + 0.008466340, + 0.008096858, + 0.007416456, + ] + ) diff = testdy - dy[:10] res = numpy.dot(diff, diff) self.assertAlmostEqual(0, res) @@ -111,10 +130,12 @@ def testParser2(self): self.assertTrue(dx is None) return + # End of class TestPDFParset # ---------------------------------------------------------------------------- + @unittest.skipUnless(has_srreal, _msg_nosrreal) @unittest.skipUnless(has_structure, _msg_nostructure) class TestPDFGenerator(unittest.TestCase): @@ -123,15 +144,15 @@ def setUp(self): self.gen = PDFGenerator() return - def testGenerator(self): qmax = 27.0 gen = self.gen - gen.setScatteringType('N') - self.assertEqual('N', gen.getScatteringType()) + gen.setScatteringType("N") + self.assertEqual("N", gen.getScatteringType()) gen.setQmax(qmax) self.assertAlmostEqual(qmax, gen.getQmax()) from diffpy.structure import PDFFitStructure + stru = PDFFitStructure() ciffile = datafile("ni.cif") stru.read(ciffile) @@ -158,12 +179,13 @@ def testGenerator(self): # output, we just have to make sure we can calculate from the # PDFGenerator interface. from diffpy.srreal.pdfcalculator import PDFCalculator + calc = PDFCalculator() calc.rstep = r[1] - r[0] calc.rmin = r[0] calc.rmax = r[-1] + 0.5 * calc.rstep calc.qmax = qmax - calc.setScatteringFactorTableByType('N') + calc.setScatteringFactorTableByType("N") calc.eval(stru) yref = calc.pdf @@ -172,10 +194,8 @@ def testGenerator(self): self.assertAlmostEqual(0, res) return - def test_setQmin(self): - """Verify qmin is propagated to the calculator object. - """ + """Verify qmin is propagated to the calculator object.""" gen = self.gen self.assertEqual(0, gen.getQmin()) self.assertEqual(0, gen._calc.qmin) @@ -184,37 +204,37 @@ def test_setQmin(self): self.assertEqual(0.93, gen._calc.qmin) return + # End of class TestPDFGenerator # ---------------------------------------------------------------------------- + @unittest.skipUnless(has_srreal, _msg_nosrreal) @unittest.skipUnless(has_structure, _msg_nostructure) class TestPDFContribution(unittest.TestCase): def setUp(self): - self.pc = PDFContribution('pdf') + self.pc = PDFContribution("pdf") return - def test_setQmax(self): - """check PDFContribution.setQmax() - """ + """check PDFContribution.setQmax()""" from diffpy.structure import Structure + pc = self.pc pc.setQmax(21) - pc.addStructure('empty', Structure()) + pc.addStructure("empty", Structure()) self.assertEqual(21, pc.empty.getQmax()) pc.setQmax(22) self.assertEqual(22, pc.getQmax()) self.assertEqual(22, pc.empty.getQmax()) return - def test_getQmax(self): - """check PDFContribution.getQmax() - """ + """check PDFContribution.getQmax()""" from diffpy.structure import Structure + # cover all code branches in PDFContribution._getMetaValue # (1) contribution metadata pc1 = self.pc @@ -222,54 +242,56 @@ def test_getQmax(self): pc1.setQmax(17) self.assertEqual(17, pc1.getQmax()) # (2) contribution metadata - pc2 = PDFContribution('pdf') - pc2.addStructure('empty', Structure()) + pc2 = PDFContribution("pdf") + pc2.addStructure("empty", Structure()) pc2.empty.setQmax(18) self.assertEqual(18, pc2.getQmax()) # (3) profile metadata - pc3 = PDFContribution('pdf') - pc3.profile.meta['qmax'] = 19 + pc3 = PDFContribution("pdf") + pc3.profile.meta["qmax"] = 19 self.assertEqual(19, pc3.getQmax()) return - def test_savetxt(self): "check PDFContribution.savetxt()" from diffpy.structure import Structure + pc = self.pc pc.loadData(datafile("si-q27r60-xray.gr")) pc.setCalculationRange(0, 10) - pc.addStructure('empty', Structure()) + pc.addStructure("empty", Structure()) fp = io.BytesIO() self.assertRaises(SrFitError, pc.savetxt, fp) pc.evaluate() pc.savetxt(fp) txt = fp.getvalue().decode() - nlines = len(txt.strip().split('\n')) + nlines = len(txt.strip().split("\n")) self.assertEqual(1001, nlines) return - def test_pickling(self): "validate PDFContribution.residual() after pickling." from itertools import chain + from diffpy.structure import loadStructure + pc = self.pc pc.loadData(datafile("ni-q27r100-neutron.gr")) ni = loadStructure(datafile("ni.cif")) ni.Uisoequiv = 0.003 - pc.addStructure('ni', ni) + pc.addStructure("ni", ni) pc.setCalculationRange(0, 10) pc2 = pickle.loads(pickle.dumps(pc)) res0 = pc.residual() self.assertTrue(numpy.array_equal(res0, pc2.residual())) - for p in chain(pc.iterPars('Uiso'), pc2.iterPars('Uiso')): + for p in chain(pc.iterPars("Uiso"), pc2.iterPars("Uiso")): p.value = 0.004 res1 = pc.residual() self.assertFalse(numpy.allclose(res0, res1)) self.assertTrue(numpy.array_equal(res1, pc2.residual())) return + # End of class TestPDFContribution # ---------------------------------------------------------------------------- diff --git a/src/diffpy/srfit/tests/testprofile.py b/src/diffpy/srfit/tests/testprofile.py index 78f221d9..428fcac2 100644 --- a/src/diffpy/srfit/tests/testprofile.py +++ b/src/diffpy/srfit/tests/testprofile.py @@ -15,14 +15,14 @@ """Tests for refinableobj module.""" -import unittest -import re import io +import re +import unittest -from numpy import array, arange, array_equal, ones_like, allclose +from numpy import allclose, arange, array, array_equal, ones_like -from diffpy.srfit.fitbase.profile import Profile from diffpy.srfit.exceptions import SrFitError +from diffpy.srfit.fitbase.profile import Profile from diffpy.srfit.tests.utils import datafile @@ -55,9 +55,9 @@ def testSetObservedProfile(self): prof = self.profile prof.setObservedProfile(x, y, dy) - self.assertTrue( array_equal(x, prof.xobs) ) - self.assertTrue( array_equal(y, prof.yobs) ) - self.assertTrue( array_equal(dy, prof.dyobs) ) + self.assertTrue(array_equal(x, prof.xobs)) + self.assertTrue(array_equal(y, prof.yobs)) + self.assertTrue(array_equal(dy, prof.dyobs)) # Make a profile with undefined dy x = arange(0, 10, 0.1) @@ -66,18 +66,17 @@ def testSetObservedProfile(self): self.profile.setObservedProfile(x, y, dy) - self.assertTrue( array_equal(x, prof.xobs) ) - self.assertTrue( array_equal(y, prof.yobs) ) - self.assertTrue( array_equal(ones_like(prof.xobs), prof.dyobs)) + self.assertTrue(array_equal(x, prof.xobs)) + self.assertTrue(array_equal(y, prof.yobs)) + self.assertTrue(array_equal(ones_like(prof.xobs), prof.dyobs)) # Get the ranged profile to make sure its the same - self.assertTrue( array_equal(x, prof.x) ) - self.assertTrue( array_equal(y, prof.y) ) - self.assertTrue( array_equal(ones_like(prof.xobs), prof.dy)) + self.assertTrue(array_equal(x, prof.x)) + self.assertTrue(array_equal(y, prof.y)) + self.assertTrue(array_equal(ones_like(prof.xobs), prof.dy)) return - def testSetCalculationRange(self): """Test the setCalculationRange method.""" x = arange(2, 9.6, 0.5) @@ -110,26 +109,24 @@ def testSetCalculationRange(self): self.assertTrue(array_equal(y, prof.y)) self.assertTrue(array_equal(dy, prof.dy)) # Test xmin > xmax - self.assertRaises(ValueError, prof.setCalculationRange, - xmin=10, xmax=3) + self.assertRaises(ValueError, prof.setCalculationRange, xmin=10, xmax=3) # Test xmax - xmin < dx - self.assertRaises(ValueError, prof.setCalculationRange, - xmin=3, xmax=3.9, dx=1.0) + self.assertRaises(ValueError, prof.setCalculationRange, xmin=3, xmax=3.9, dx=1.0) # Test dx <= 0 self.assertRaises(ValueError, prof.setCalculationRange, dx=0) self.assertRaises(ValueError, prof.setCalculationRange, dx=-0.000001) # using string other than 'obs' - self.assertRaises(ValueError, prof.setCalculationRange, xmin='oobs') - self.assertRaises(ValueError, prof.setCalculationRange, xmax='oobs') - self.assertRaises(ValueError, prof.setCalculationRange, dx='oobs') + self.assertRaises(ValueError, prof.setCalculationRange, xmin="oobs") + self.assertRaises(ValueError, prof.setCalculationRange, xmax="oobs") + self.assertRaises(ValueError, prof.setCalculationRange, dx="oobs") # This should be alright prof.setCalculationRange(3, 5) - prof.setCalculationRange(xmin='obs', xmax=7, dx=0.001) + prof.setCalculationRange(xmin="obs", xmax=7, dx=0.001) self.assertEqual(5001, len(prof.x)) self.assertEqual(len(prof.x), len(prof.y)) self.assertEqual(len(prof.x), len(prof.dy)) # Test an internal bound - prof.setCalculationRange(4, 7, dx='obs') + prof.setCalculationRange(4, 7, dx="obs") self.assertTrue(array_equal(prof.x, arange(4, 7.1, 0.5))) self.assertTrue(array_equal(prof.y, arange(4, 7.1, 0.5))) self.assertTrue(array_equal(prof.y, arange(4, 7.1, 0.5))) @@ -158,7 +155,6 @@ def testSetCalculationRange(self): self.assertTrue(array_equal(prof.x, arange(4.5, 6.1, 0.5))) return - def testSetCalculationPoints(self): """Test the setCalculationPoints method.""" prof = self.profile @@ -170,11 +166,11 @@ def testSetCalculationPoints(self): # Test without data xcalc = arange(3, 12.2, 0.2) prof.setCalculationPoints(xcalc) - self.assertTrue( array_equal(xcalc, prof.x) ) + self.assertTrue(array_equal(xcalc, prof.x)) # Add the data. This should change the bounds of the calculation array. prof.setObservedProfile(x, y, dy) - self.assertTrue( array_equal(arange(3, 10.1, 0.2), prof.x ) ) + self.assertTrue(array_equal(arange(3, 10.1, 0.2), prof.x)) return @@ -190,17 +186,17 @@ def _test(p): self.assertAlmostEqual(1.802192e-3, p.dy[0]) # Test normal load - prof.loadtxt(data, usecols=(0,1,3)) + prof.loadtxt(data, usecols=(0, 1, 3)) _test(prof) # Test trying to not set unpack - prof.loadtxt(data, usecols=(0,1,3), unpack = False) + prof.loadtxt(data, usecols=(0, 1, 3), unpack=False) _test(prof) - prof.loadtxt(data, float, '#', None, None, 0, (0,1,3), False) + prof.loadtxt(data, float, "#", None, None, 0, (0, 1, 3), False) _test(prof) # Try not including dy - prof.loadtxt(data, usecols=(0,1)) + prof.loadtxt(data, usecols=(0, 1)) self.assertAlmostEqual(1e-2, prof.x[0]) self.assertAlmostEqual(1.105784e-1, prof.y[0]) self.assertAlmostEqual(1, prof.dy[0]) @@ -209,23 +205,23 @@ def _test(p): self.assertRaises(ValueError, prof.loadtxt, data, usecols=(0,)) return - def test_savetxt(self): "Check the savetxt method." prof = self.profile - self.assertRaises(SrFitError, prof.savetxt, 'foo') + self.assertRaises(SrFitError, prof.savetxt, "foo") xobs = arange(-2, 3.01, 0.25) - yobs = xobs ** 2 + yobs = xobs**2 prof.setObservedProfile(xobs, yobs) prof.ycalc = yobs.copy() fp = io.BytesIO() prof.savetxt(fp) txt = fp.getvalue().decode() - self.assertTrue(re.match(r'^# x +ycalc +y +dy\b', txt)) - nlines = len(txt.strip().split('\n')) + self.assertTrue(re.match(r"^# x +ycalc +y +dy\b", txt)) + nlines = len(txt.strip().split("\n")) self.assertEqual(22, nlines) return + # End of class TestProfile # ---------------------------------------------------------------------------- diff --git a/src/diffpy/srfit/tests/testprofilegenerator.py b/src/diffpy/srfit/tests/testprofilegenerator.py index 4fb43002..07c02037 100644 --- a/src/diffpy/srfit/tests/testprofilegenerator.py +++ b/src/diffpy/srfit/tests/testprofilegenerator.py @@ -20,8 +20,8 @@ from numpy import arange, array_equal -from diffpy.srfit.fitbase.profilegenerator import ProfileGenerator from diffpy.srfit.fitbase.profile import Profile +from diffpy.srfit.fitbase.profilegenerator import ProfileGenerator class TestProfileGenerator(unittest.TestCase): @@ -34,7 +34,6 @@ def setUp(self): self.gen.setProfile(self.profile) return - def testOperation(self): """Test the operation method.""" gen = self.gen @@ -49,7 +48,6 @@ def testOperation(self): self.assertTrue(array_equal(2 * prof.x, val)) return - def testUpdate(self): """Update and change the profile to make sure generator is flushed.""" gen = self.gen @@ -77,18 +75,17 @@ def testUpdate(self): self.assertTrue(array_equal(x, gen.value)) return - def test_pickling(self): - """Test pickling of ProfileGenerator. - """ + """Test pickling of ProfileGenerator.""" data = pickle.dumps(self.gen) gen2 = pickle.loads(data) - self.assertEqual('test', gen2.name) + self.assertEqual("test", gen2.name) x = self.profile.x self.assertTrue(array_equal(x, gen2.operation())) self.assertTrue(array_equal(3 * x, gen2(3 * x))) return + # End of class TestProfileGenerator if __name__ == "__main__": diff --git a/src/diffpy/srfit/tests/testrecipeorganizer.py b/src/diffpy/srfit/tests/testrecipeorganizer.py index 08efde92..f080c28b 100644 --- a/src/diffpy/srfit/tests/testrecipeorganizer.py +++ b/src/diffpy/srfit/tests/testrecipeorganizer.py @@ -17,18 +17,17 @@ import unittest +import numpy + from diffpy.srfit.equation.builder import EquationFactory from diffpy.srfit.fitbase.calculator import Calculator from diffpy.srfit.fitbase.parameter import Parameter -from diffpy.srfit.fitbase.recipeorganizer import equationFromString -from diffpy.srfit.fitbase.recipeorganizer import RecipeContainer -from diffpy.srfit.fitbase.recipeorganizer import RecipeOrganizer +from diffpy.srfit.fitbase.recipeorganizer import RecipeContainer, RecipeOrganizer, equationFromString from diffpy.srfit.tests.utils import capturestdout -import numpy - # ---------------------------------------------------------------------------- + class TestEquationFromString(unittest.TestCase): def testEquationFromString(self): @@ -56,7 +55,7 @@ def testEquationFromString(self): self.assertRaises(ValueError, equationFromString, "p1+p2+p3", factory) # Pass that argument in the ns dictionary - eq = equationFromString("p1+p2+p3", factory, {"p3":p3}) + eq = equationFromString("p1+p2+p3", factory, {"p3": p3}) self.assertEqual(3, len(eq.args)) self.assertTrue(p1 in eq.args) self.assertTrue(p2 in eq.args) @@ -67,17 +66,17 @@ def testEquationFromString(self): self.assertTrue("p3" not in factory.builders) # Pass and use an unregistered parameter - self.assertRaises(ValueError, equationFromString, "p1+p2+p3+p4", - factory, {"p3":p3}) + self.assertRaises(ValueError, equationFromString, "p1+p2+p3+p4", factory, {"p3": p3}) # Try to overload a registered parameter - self.assertRaises(ValueError, equationFromString, "p1+p2", - factory, {"p2":p4}) + self.assertRaises(ValueError, equationFromString, "p1+p2", factory, {"p2": p4}) return + # ---------------------------------------------------------------------------- + class TestRecipeContainer(unittest.TestCase): def setUp(self): @@ -107,14 +106,18 @@ def testAccessors(self): self.assertTrue(m1.m2.p2 is p2) self.assertTrue(m1[0] is p1) - self.assertTrue(m1[0:] == [p1,]) + self.assertTrue( + m1[0:] + == [ + p1, + ] + ) self.assertTrue(m2[0] is p2) self.assertEqual(1, len(m1)) self.assertEqual(1, len(m2)) return - def testLocateManagedObject(self): """Test the locateManagedObject method.""" m1 = self.m @@ -155,8 +158,10 @@ def testLocateManagedObject(self): return + # ---------------------------------------------------------------------------- + class TestRecipeOrganizer(unittest.TestCase): def setUp(self): @@ -169,7 +174,6 @@ def setUp(self): def tearDown(self): return - def testNewParameter(self): """Test the addParameter method.""" @@ -186,7 +190,6 @@ def testNewParameter(self): self.assertTrue(p2 is m.p2) return - def testAddParameter(self): """Test the addParameter method.""" @@ -261,7 +264,6 @@ def testConstrain(self): self.assertEqual(0, len(self.m._constraints)) self.m.constrain(p1, "2*p2") - self.assertTrue(p1.constrained) self.assertTrue(p1 in self.m._constraints) self.assertEqual(1, len(self.m._constraints)) @@ -273,7 +275,7 @@ def testConstrain(self): # Check errors on unregistered parameters self.assertRaises(ValueError, self.m.constrain, p1, "2*p3") - self.assertRaises(ValueError, self.m.constrain, p1, "2*p2", {"p2":p3}) + self.assertRaises(ValueError, self.m.constrain, p1, "2*p2", {"p2": p3}) # Remove the constraint self.m.unconstrain(p1) @@ -298,21 +300,21 @@ def testRestrain(self): self.m._eqfactory.registerArgument("p2", p2) self.assertEqual(0, len(self.m._restraints)) - r = self.m.restrain("p1+p2", ub = 10) + r = self.m.restrain("p1+p2", ub=10) self.assertEqual(1, len(self.m._restraints)) p2.setValue(10) self.assertEqual(1, r.penalty()) self.m.unrestrain(r) self.assertEqual(0, len(self.m._restraints)) - r = self.m.restrain(p1, ub = 10) + r = self.m.restrain(p1, ub=10) self.assertEqual(1, len(self.m._restraints)) p1.setValue(11) self.assertEqual(1, r.penalty()) # Check errors on unregistered parameters self.assertRaises(ValueError, self.m.restrain, "2*p3") - self.assertRaises(ValueError, self.m.restrain, "2*p2", ns = {"p2":p3}) + self.assertRaises(ValueError, self.m.restrain, "2*p2", ns={"p2": p3}) return def testGetConstraints(self): @@ -384,7 +386,7 @@ def __call__(self, x): A = self.A.getValue() c = self.center.getValue() w = self.width.getValue() - return A * numpy.exp(-0.5*((x-c)/w)**2) + return A * numpy.exp(-0.5 * ((x - c) / w) ** 2) # End class GCalc @@ -397,27 +399,27 @@ def __call__(self, x): self.m.g.center.setValue(3.0) - self.assertTrue(numpy.array_equal(numpy.exp(-0.5*((x-3.0)/0.1)**2), - g(x))) + self.assertTrue(numpy.array_equal(numpy.exp(-0.5 * ((x - 3.0) / 0.1) ** 2), g(x))) self.m.g.center.setValue(5.0) - self.assertTrue(numpy.array_equal(numpy.exp(-0.5*((x-5.0)/0.1)**2), - g(x))) + self.assertTrue(numpy.array_equal(numpy.exp(-0.5 * ((x - 5.0) / 0.1) ** 2), g(x))) # Use this in another equation eq = self.m.registerStringFunction("g/x - 1", "pdf") - self.assertTrue(numpy.array_equal(g(x)/x - 1, eq())) + self.assertTrue(numpy.array_equal(g(x) / x - 1, eq())) return def testRegisterFunction(self): """Test registering various functions.""" + def g1(A, c, w, x): - return A * numpy.exp(-0.5*((x-c)/w)**2) + return A * numpy.exp(-0.5 * ((x - c) / w) ** 2) + def g2(A): - return A+1 + return A + 1 eq = self.m.registerFunction(g1, "g") @@ -430,12 +432,11 @@ def g2(A): self.m.c.setValue(3.0) self.m.w.setValue(0.1) - self.assertTrue(numpy.array_equal(numpy.exp(-0.5*((x-3.0)/0.1)**2), - eq())) + self.assertTrue(numpy.array_equal(numpy.exp(-0.5 * ((x - 3.0) / 0.1) ** 2), eq())) # Use this in another equation eq2 = self.m.registerStringFunction("g/x - 1", "pdf") - self.assertTrue(numpy.array_equal(eq()/x - 1, eq2())) + self.assertTrue(numpy.array_equal(eq() / x - 1, eq2())) # Make sure we can swap out "g". self.m.registerFunction(g2, "g") @@ -443,8 +444,11 @@ def g2(A): # Try a bound method class temp(object): - def eval(self): return 1.23 - def __call__(self): return 4.56 + def eval(self): + return 1.23 + + def __call__(self): + return 4.56 t = temp() eq = self.m.registerFunction(t.eval, "eval") @@ -494,50 +498,48 @@ def testRegisterStringFunction(self): return - def test_releaseOldEquations(self): - """Verify EquationFactory does not hold temporary equations. - """ - self.m._newParameter('x', 12) - self.assertEqual(36, self.m.evaluateEquation('3 * x')) + """Verify EquationFactory does not hold temporary equations.""" + self.m._newParameter("x", 12) + self.assertEqual(36, self.m.evaluateEquation("3 * x")) self.assertEqual(0, len(self.m._eqfactory.equations)) return - def test_show(self): - """Verify output from the show function. - """ + """Verify output from the show function.""" + def capture_show(*args, **kwargs): rv = capturestdout(self.m.show, *args, **kwargs) return rv - self.assertEqual('', capture_show()) - self.m._newParameter('x', 1) - self.m._newParameter('y', 2) + + self.assertEqual("", capture_show()) + self.m._newParameter("x", 1) + self.m._newParameter("y", 2) out1 = capture_show() - lines1 = out1.strip().split('\n') + lines1 = out1.strip().split("\n") self.assertEqual(4, len(lines1)) - self.assertTrue('Parameters' in lines1) - self.assertFalse('Constraints' in lines1) - self.assertFalse('Restraints' in lines1) - self.m._newParameter('z', 7) - self.m.constrain('y', '3 * z') + self.assertTrue("Parameters" in lines1) + self.assertFalse("Constraints" in lines1) + self.assertFalse("Restraints" in lines1) + self.m._newParameter("z", 7) + self.m.constrain("y", "3 * z") out2 = capture_show() - lines2 = out2.strip().split('\n') + lines2 = out2.strip().split("\n") self.assertEqual(9, len(lines2)) - self.assertTrue('Parameters' in lines2) - self.assertTrue('Constraints' in lines2) - self.assertFalse('Restraints' in lines2) - self.m.restrain('z', lb=2, ub=3, sig=0.001) + self.assertTrue("Parameters" in lines2) + self.assertTrue("Constraints" in lines2) + self.assertFalse("Restraints" in lines2) + self.m.restrain("z", lb=2, ub=3, sig=0.001) out3 = capture_show() - lines3 = out3.strip().split('\n') + lines3 = out3.strip().split("\n") self.assertEqual(13, len(lines3)) - self.assertTrue('Parameters' in lines3) - self.assertTrue('Constraints' in lines3) - self.assertTrue('Restraints' in lines3) - out4 = capture_show(pattern='x') - lines4 = out4.strip().split('\n') + self.assertTrue("Parameters" in lines3) + self.assertTrue("Constraints" in lines3) + self.assertTrue("Restraints" in lines3) + out4 = capture_show(pattern="x") + lines4 = out4.strip().split("\n") self.assertEqual(9, len(lines4)) - out5 = capture_show(pattern='^') + out5 = capture_show(pattern="^") self.assertEqual(out3, out5) # check output with another level of hierarchy self.m._addObject(RecipeOrganizer("foo"), self.m._containers) @@ -545,11 +547,12 @@ def capture_show(*args, **kwargs): out6 = capture_show() self.assertTrue("foo.bar" in out6) # filter out foo.bar - out7 = capture_show('^(?!foo).') + out7 = capture_show("^(?!foo).") self.assertFalse("foo.bar" in out7) self.assertEqual(out3, out7) return + # ---------------------------------------------------------------------------- if __name__ == "__main__": diff --git a/src/diffpy/srfit/tests/testrestraint.py b/src/diffpy/srfit/tests/testrestraint.py index 2968dd32..610a62ab 100644 --- a/src/diffpy/srfit/tests/testrestraint.py +++ b/src/diffpy/srfit/tests/testrestraint.py @@ -17,10 +17,10 @@ import unittest -from diffpy.srfit.fitbase.restraint import Restraint -from diffpy.srfit.fitbase.recipeorganizer import equationFromString -from diffpy.srfit.fitbase.parameter import Parameter from diffpy.srfit.equation.builder import EquationFactory +from diffpy.srfit.fitbase.parameter import Parameter +from diffpy.srfit.fitbase.recipeorganizer import equationFromString +from diffpy.srfit.fitbase.restraint import Restraint class TestRestraint(unittest.TestCase): @@ -63,6 +63,7 @@ def testRestraint(self): # Make a really large number to check the upper bound import numpy + r.ub = numpy.inf p1.setValue(1e100) self.assertEqual(0, r.penalty()) diff --git a/src/diffpy/srfit/tests/testsas.py b/src/diffpy/srfit/tests/testsas.py index 9122cf97..2e94114f 100644 --- a/src/diffpy/srfit/tests/testsas.py +++ b/src/diffpy/srfit/tests/testsas.py @@ -20,12 +20,12 @@ import numpy from diffpy.srfit.sas import SASGenerator, SASParser, SASProfile -from diffpy.srfit.tests.utils import datafile -from diffpy.srfit.tests.utils import has_sas, _msg_nosas from diffpy.srfit.sas.sasimport import sasimport +from diffpy.srfit.tests.utils import _msg_nosas, datafile, has_sas # ---------------------------------------------------------------------------- + @unittest.skipUnless(has_sas, _msg_nosas) class TestSASParser(unittest.TestCase): @@ -36,43 +36,47 @@ def testParser(self): x, y, dx, dy = parser.getData() - testx = numpy.array([0.002618, 0.007854, 0.01309, 0.01832, 0.02356, - 0.02879, 0.03402, 0.03925, 0.04448, 0.0497]) + testx = numpy.array( + [0.002618, 0.007854, 0.01309, 0.01832, 0.02356, 0.02879, 0.03402, 0.03925, 0.04448, 0.0497] + ) diff = testx - x res = numpy.dot(diff, diff) self.assertAlmostEqual(0, res) - testy = numpy.array([ 0.02198, 0.02201, 0.02695, 0.02645, 0.03024, - 0.3927, 7.305, 17.43, 13.43, 8.346]) + testy = numpy.array([0.02198, 0.02201, 0.02695, 0.02645, 0.03024, 0.3927, 7.305, 17.43, 13.43, 8.346]) diff = testy - y res = numpy.dot(diff, diff) self.assertAlmostEqual(0, res) - testdy = numpy.array([ 0.002704, 0.001643, 0.002452, 0.001769, - 0.001531, 0.1697, 1.006, 0.5351, 0.3677, 0.191]) + testdy = numpy.array( + [0.002704, 0.001643, 0.002452, 0.001769, 0.001531, 0.1697, 1.006, 0.5351, 0.3677, 0.191] + ) diff = testdy - dy res = numpy.dot(diff, diff) self.assertAlmostEqual(0, res) - testdx = numpy.array([0.0004091, 0.005587, 0.005598, 0.005624, - 0.005707, 0.005975, 0.006264, 0.006344, 0.006424, 0.006516]) + testdx = numpy.array( + [0.0004091, 0.005587, 0.005598, 0.005624, 0.005707, 0.005975, 0.006264, 0.006344, 0.006424, 0.006516] + ) diff = testdx - dx res = numpy.dot(diff, diff) self.assertAlmostEqual(0, res) return + # End of class TestSASParser # ---------------------------------------------------------------------------- + @unittest.skipUnless(has_sas, _msg_nosas) class TestSASGenerator(unittest.TestCase): def testGenerator(self): # Test generator output - SphereModel = sasimport('sas.models.SphereModel').SphereModel + SphereModel = sasimport("sas.models.SphereModel").SphereModel model = SphereModel() gen = SASGenerator("sphere", model) @@ -88,8 +92,7 @@ def testGenerator(self): self.assertEqual(defval, par.getValue()) self.assertEqual(defval, model.getParam(pname)) - - r = numpy.arange(1, 10, 0.1, dtype = float) + r = numpy.arange(1, 10, 0.1, dtype=float) y = gen(r) refy = model.evalDistribution(r) diff = y - refy @@ -98,16 +101,15 @@ def testGenerator(self): return - def testGenerator2(self): # Test generator with a profile - EllipsoidModel = sasimport('sas.models.EllipsoidModel').EllipsoidModel + EllipsoidModel = sasimport("sas.models.EllipsoidModel").EllipsoidModel model = EllipsoidModel() gen = SASGenerator("ellipsoid", model) # Load the data using SAS tools - Loader = sasimport('sas.dataloader.loader').Loader + Loader = sasimport("sas.dataloader.loader").Loader loader = Loader() data = datafile("sas_ellipsoid_testdata.txt") datainfo = loader.load(data) @@ -125,6 +127,7 @@ def testGenerator2(self): self.assertAlmostEqual(0, res) return + # End of class TestSASGenerator if __name__ == "__main__": diff --git a/src/diffpy/srfit/tests/testsgconstraints.py b/src/diffpy/srfit/tests/testsgconstraints.py index 01c4d49b..01bb8545 100644 --- a/src/diffpy/srfit/tests/testsgconstraints.py +++ b/src/diffpy/srfit/tests/testsgconstraints.py @@ -19,12 +19,11 @@ import numpy -from diffpy.srfit.tests.utils import datafile -from diffpy.srfit.tests.utils import has_pyobjcryst, _msg_nopyobjcryst -from diffpy.srfit.tests.utils import has_structure, _msg_nostructure +from diffpy.srfit.tests.utils import _msg_nopyobjcryst, _msg_nostructure, datafile, has_pyobjcryst, has_structure # ---------------------------------------------------------------------------- + class TestSGConstraints(unittest.TestCase): @unittest.skipUnless(has_pyobjcryst, _msg_nopyobjcryst) @@ -51,16 +50,16 @@ def test_ObjCryst_constrainSpaceGroup(self): # Check the orthorhombic lattice l = stru.getLattice() - self.assertTrue( l.alpha.const ) - self.assertTrue( l.beta.const ) - self.assertTrue( l.gamma.const ) - self.assertEqual(pi/2, l.alpha.getValue()) - self.assertEqual(pi/2, l.beta.getValue()) - self.assertEqual(pi/2, l.gamma.getValue()) - - self.assertFalse( l.a.const ) - self.assertFalse( l.b.const ) - self.assertFalse( l.c.const ) + self.assertTrue(l.alpha.const) + self.assertTrue(l.beta.const) + self.assertTrue(l.gamma.const) + self.assertEqual(pi / 2, l.alpha.getValue()) + self.assertEqual(pi / 2, l.beta.getValue()) + self.assertEqual(pi / 2, l.gamma.getValue()) + + self.assertFalse(l.a.const) + self.assertFalse(l.b.const) + self.assertFalse(l.c.const) self.assertEqual(0, len(l._constraints)) # Now make sure the scatterers are constrained properly @@ -96,12 +95,12 @@ def test_ObjCryst_constrainSpaceGroup(self): # Nor can we make them into variables from diffpy.srfit.fitbase.fitrecipe import FitRecipe + f = FitRecipe() self.assertRaises(ValueError, f.addVar, mn.x) return - @unittest.skipUnless(has_structure, _msg_nostructure) def test_DiffPy_constrainAsSpaceGroup(self): """Test the constrainAsSpaceGroup function.""" @@ -111,14 +110,14 @@ def test_DiffPy_constrainAsSpaceGroup(self): stru = makeLaMnO3_P1() parset = DiffpyStructureParSet("LaMnO3", stru) - sgpars = constrainAsSpaceGroup(parset, "P b n m", - scatterers = parset.getScatterers()[::2], - constrainadps = True) + sgpars = constrainAsSpaceGroup( + parset, "P b n m", scatterers=parset.getScatterers()[::2], constrainadps=True + ) # Make sure that the new parameters were created for par in sgpars: self.assertNotEqual(None, par) - self.assertNotEqual(None, par.getValue() ) + self.assertNotEqual(None, par.getValue()) # Test the unconstrained atoms for scatterer in parset.getScatterers()[1::2]: @@ -137,10 +136,13 @@ def test_DiffPy_constrainAsSpaceGroup(self): def _consttest(par): return par.const + def _constrainedtest(par): return par.constrained + def _proxytest(par): return par in proxied + def _alltests(par): return _consttest(par) or _constrainedtest(par) or _proxytest(par) @@ -152,26 +154,24 @@ def _alltests(par): self.assertTrue(test) test = False - for par in [scatterer.U11, scatterer.U22, scatterer.U33, - scatterer.U12, scatterer.U13, scatterer.U23]: + for par in [scatterer.U11, scatterer.U22, scatterer.U33, scatterer.U12, scatterer.U13, scatterer.U23]: test |= _alltests(par) self.assertTrue(test) return - @unittest.skipUnless(has_structure, _msg_nostructure) def test_ConstrainAsSpaceGroup_args(self): - """Test the arguments processing of constrainAsSpaceGroup function. - """ + """Test the arguments processing of constrainAsSpaceGroup function.""" from diffpy.srfit.structure.diffpyparset import DiffpyStructureParSet from diffpy.srfit.structure.sgconstraints import constrainAsSpaceGroup from diffpy.structure.spacegroups import GetSpaceGroup + stru = makeLaMnO3_P1() parset = DiffpyStructureParSet("LaMnO3", stru) sgpars = constrainAsSpaceGroup(parset, "P b n m") - sg = GetSpaceGroup('P b n m') + sg = GetSpaceGroup("P b n m") parset2 = DiffpyStructureParSet("LMO", makeLaMnO3_P1()) sgpars2 = constrainAsSpaceGroup(parset2, sg) list(sgpars) @@ -179,20 +179,23 @@ def test_ConstrainAsSpaceGroup_args(self): self.assertEqual(sgpars.names, sgpars2.names) return + # End of class TestSGConstraints # Local helper functions ----------------------------------------------------- + def makeLaMnO3_P1(): from diffpy.structure import Structure + stru = Structure() - stru.read(datafile('LaMnO3.stru')) + stru.read(datafile("LaMnO3.stru")) return stru def makeLaMnO3(): - from pyobjcryst.crystal import Crystal from pyobjcryst.atom import Atom + from pyobjcryst.crystal import Crystal from pyobjcryst.scatteringpower import ScatteringPowerAtom pi = numpy.pi @@ -201,31 +204,32 @@ def makeLaMnO3(): crystal.SetName("LaMnO3") # La1 sp = ScatteringPowerAtom("La1", "La") - sp.SetBiso(8*pi*pi*0.003) + sp.SetBiso(8 * pi * pi * 0.003) atom = Atom(0.996096, 0.0321494, 0.25, "La1", sp) crystal.AddScatteringPower(sp) crystal.AddScatterer(atom) # Mn1 sp = ScatteringPowerAtom("Mn1", "Mn") - sp.SetBiso(8*pi*pi*0.003) + sp.SetBiso(8 * pi * pi * 0.003) atom = Atom(0, 0.5, 0, "Mn1", sp) crystal.AddScatteringPower(sp) crystal.AddScatterer(atom) # O1 sp = ScatteringPowerAtom("O1", "O") - sp.SetBiso(8*pi*pi*0.003) + sp.SetBiso(8 * pi * pi * 0.003) atom = Atom(0.0595746, 0.496164, 0.25, "O1", sp) crystal.AddScatteringPower(sp) crystal.AddScatterer(atom) # O2 sp = ScatteringPowerAtom("O2", "O") - sp.SetBiso(8*pi*pi*0.003) + sp.SetBiso(8 * pi * pi * 0.003) atom = Atom(0.720052, 0.289387, 0.0311126, "O2", sp) crystal.AddScatteringPower(sp) crystal.AddScatterer(atom) return crystal + # ---------------------------------------------------------------------------- if __name__ == "__main__": diff --git a/src/diffpy/srfit/tests/testtagmanager.py b/src/diffpy/srfit/tests/testtagmanager.py index 5518f3aa..c481cf2f 100644 --- a/src/diffpy/srfit/tests/testtagmanager.py +++ b/src/diffpy/srfit/tests/testtagmanager.py @@ -20,6 +20,7 @@ from diffpy.srfit.util.tagmanager import TagManager + ############################################################################## class TestTagManager(unittest.TestCase): @@ -32,8 +33,7 @@ def tearDown(self): return def test_tag(self): - """check TagManager.tag() - """ + """check TagManager.tag()""" m = self.m obj = 3 m.tag(obj, "3", "three") @@ -48,8 +48,7 @@ def test_tag(self): return def test_untag(self): - """check TagManager.untag() - """ + """check TagManager.untag()""" m = self.m obj = 3 m.tag(obj, "3", "three", "tri", "tres", "trois") @@ -70,12 +69,11 @@ def test_untag(self): return def test_union_and_intersection(self): - """check TagManager.union() and TagManager.intersection() - """ + """check TagManager.union() and TagManager.intersection()""" m = self.m m.tag(3, "3", "number") m.tag(4, "4", "number") - objs = set([3,4]) + objs = set([3, 4]) self.assertEqual(m.union(), set()) self.assertEqual(m.union("number"), objs) self.assertEqual(m.union("3"), set([3])) @@ -95,22 +93,22 @@ def test_union_and_intersection(self): return def test_hasTags(self): - """check TagManager.hasTags() - """ + """check TagManager.hasTags()""" m = self.m m.tag(3, "3", "number") m.tag(4, "4", "number") - self.assertTrue( m.hasTags(3, "3") ) - self.assertTrue( m.hasTags(3, "3", "number") ) - self.assertFalse( m.hasTags(3, "3", "4") ) + self.assertTrue(m.hasTags(3, "3")) + self.assertTrue(m.hasTags(3, "3", "number")) + self.assertFalse(m.hasTags(3, "3", "4")) self.assertRaises(KeyError, m.hasTags, 3, "fail") m.silent = True self.assertFalse(m.hasTags(3, "fail")) return + # End of class TestTagManager -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() # End of file diff --git a/src/diffpy/srfit/tests/testvisitors.py b/src/diffpy/srfit/tests/testvisitors.py index 0250f064..bbde25eb 100644 --- a/src/diffpy/srfit/tests/testvisitors.py +++ b/src/diffpy/srfit/tests/testvisitors.py @@ -17,10 +17,11 @@ import unittest -import diffpy.srfit.equation.visitors as visitors import diffpy.srfit.equation.literals as literals +import diffpy.srfit.equation.visitors as visitors from diffpy.srfit.tests.utils import _makeArgs + class TestValidator(unittest.TestCase): def testSimpleFunction(self): @@ -72,6 +73,7 @@ def testSimpleFunction(self): # Fix the operation of plus import numpy + plus.operation = numpy.add validator.reset() mult.identify(validator) @@ -85,6 +87,7 @@ def testSimpleFunction(self): return + class TestArgFinder(unittest.TestCase): def testSimpleFunction(self): @@ -134,6 +137,7 @@ def testArg(self): self.assertTrue(args[0] is v1) return + class TestSwapper(unittest.TestCase): def testSimpleFunction(self): diff --git a/src/diffpy/srfit/tests/testweakrefcallable.py b/src/diffpy/srfit/tests/testweakrefcallable.py index a3d589ca..f3a9ece4 100644 --- a/src/diffpy/srfit/tests/testweakrefcallable.py +++ b/src/diffpy/srfit/tests/testweakrefcallable.py @@ -18,46 +18,42 @@ """ -import unittest import pickle +import unittest from diffpy.srfit.fitbase import FitContribution from diffpy.srfit.fitbase.parameter import Parameter -from diffpy.srfit.util.weakrefcallable import weak_ref, WeakBoundMethod +from diffpy.srfit.util.weakrefcallable import WeakBoundMethod, weak_ref # ---------------------------------------------------------------------------- + class TestWeakBoundMethod(unittest.TestCase): def setUp(self): - self.f = FitContribution('f') - self.f.setEquation('7') + self.f = FitContribution("f") + self.f.setEquation("7") self.w = weak_ref(self.f._eq._flush, fallback=_fallback_example) return - def tearDown(self): self.f = None self.assertTrue(None is self.w._wref()) - obj, args, kw = self.w('any', 'argument', foo=37) + obj, args, kw = self.w("any", "argument", foo=37) self.assertTrue(obj is self.w) - self.assertEqual(('any', 'argument'), args) - self.assertEqual({'foo' : 37}, kw) + self.assertEqual(("any", "argument"), args) + self.assertEqual({"foo": 37}, kw) return - def test___init__(self): - """check WeakBoundMethod.__init__() - """ + """check WeakBoundMethod.__init__()""" self.assertTrue(self.w.fallback is _fallback_example) wf = weak_ref(self.f._flush) self.assertTrue(None is wf.fallback) return - def test___call__(self): - """check WeakBoundMethod.__call__() - """ + """check WeakBoundMethod.__call__()""" f = self.f self.assertEqual(7, f.evaluate()) self.assertEqual(7, f._eq._value) @@ -65,18 +61,16 @@ def test___call__(self): self.w(()) self.assertTrue(None is f._eq._value) # check WeakBoundMethod behavior with no fallback - x = Parameter('x', value=3) + x = Parameter("x", value=3) wgetx = weak_ref(x.getValue) self.assertEqual(3, wgetx()) del x self.assertRaises(ReferenceError, wgetx) return - def test___hash__(self): - """check WeakBoundMethod.__hash__() - """ - f1 = FitContribution('f1') + """check WeakBoundMethod.__hash__()""" + f1 = FitContribution("f1") w1 = weak_ref(f1._flush) h0 = hash(w1) del f1 @@ -87,11 +81,9 @@ def test___hash__(self): self.assertEqual(hash(w1c1), hash(w1c2)) return - def test___eq__(self): - """check WeakBoundMethod.__eq__() - """ - f1 = FitContribution('f1') + """check WeakBoundMethod.__eq__()""" + f1 = FitContribution("f1") w1 = weak_ref(f1._flush) w2 = weak_ref(f1._flush) self.assertEqual(w1, w2) @@ -108,10 +100,8 @@ def test___eq__(self): self.assertEqual(w1, w1cc) return - def test_pickling(self): - """Verify unpickling works when it involves __hash__ call. - """ + """Verify unpickling works when it involves __hash__ call.""" holder = set([self.w]) objs = [holder, self.f._eq, self.w] data = pickle.dumps(objs) @@ -121,13 +111,11 @@ def test_pickling(self): self.assertTrue(feq2 is w2._wref()) return - def test_observable_deregistration(self): - """check if Observable drops dead Observer. - """ + """check if Observable drops dead Observer.""" f = self.f - x = f.newParameter('x', 5) - f.setEquation('3 * x') + x = f.newParameter("x", 5) + f.setEquation("3 * x") self.assertEqual(15, f.evaluate()) self.assertEqual(15, f._eq._value) # get one of the observer callables that are associated with f @@ -146,15 +134,17 @@ def test_observable_deregistration(self): self.assertEqual(0, len(x._observers)) return + # End of class TestWeakBoundMethod # Local Routines ------------------------------------------------------------- + def _fallback_example(wbm, *args, **kwargs): return (wbm, args, kwargs) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() # End of file diff --git a/src/diffpy/srfit/tests/utils.py b/src/diffpy/srfit/tests/utils.py index 963bbd64..71c6b135 100644 --- a/src/diffpy/srfit/tests/utils.py +++ b/src/diffpy/srfit/tests/utils.py @@ -16,64 +16,71 @@ """Helper routines for testing.""" import sys + import six import diffpy.srfit.equation.literals as literals from diffpy.srfit.sas.sasimport import sasimport from diffpy.srfit.tests import logger - # Resolve availability of optional third-party packages. # srfit-sasview or sasview try: _msg_nosas = "No module named 'sas.pr.invertor'" - sasimport('sas.pr.invertor') + sasimport("sas.pr.invertor") _msg_nosas = "No module named 'sas.models'" - sasimport('sas.models') + sasimport("sas.models") has_sas = True except ImportError as e: has_sas = False - logger.warning('%s, SaS tests skipped.', e) + logger.warning("%s, SaS tests skipped.", e) # diffpy.structure _msg_nostructure = "No module named 'diffpy.structure'" try: - import diffpy.structure as m; del m + import diffpy.structure as m + + del m has_structure = True except ImportError: has_structure = False - logger.warning('Cannot import diffpy.structure, Structure tests skipped.') + logger.warning("Cannot import diffpy.structure, Structure tests skipped.") # pyobjcryst _msg_nopyobjcryst = "No module named 'pyobjcryst'" try: - import pyobjcryst as m; del m + import pyobjcryst as m + + del m has_pyobjcryst = True except ImportError: has_pyobjcryst = False - logger.warning('Cannot import pyobjcryst, pyobjcryst tests skipped.') + logger.warning("Cannot import pyobjcryst, pyobjcryst tests skipped.") # diffpy.srreal _msg_nosrreal = "No module named 'diffpy.srreal'" try: - import diffpy.srreal.pdfcalculator as m; del m + import diffpy.srreal.pdfcalculator as m + + del m has_srreal = True except ImportError: has_srreal = False - logger.warning('Cannot import diffpy.srreal, PDF tests skipped.') + logger.warning("Cannot import diffpy.srreal, PDF tests skipped.") # Helper functions for testing ----------------------------------------------- + def _makeArgs(num): args = [] for i in range(num): - j=i+1 - args.append(literals.Argument(name="v%i"%j, value=j)) + j = i + 1 + args.append(literals.Argument(name="v%i" % j, value=j)) return args @@ -83,6 +90,7 @@ def noObserversInGlobalBuilders(): Ensure objects are not immortal due to a reference from static value. """ from diffpy.srfit.equation.builder import _builders + rv = True for n, b in _builders.items(): if b.literal and b.literal._observers: @@ -93,13 +101,13 @@ def noObserversInGlobalBuilders(): def datafile(filename): from pkg_resources import resource_filename + rv = resource_filename(__name__, "testdata/" + filename) return rv def capturestdout(f, *args, **kwargs): - """Capture the standard output from a call of function f. - """ + """Capture the standard output from a call of function f.""" savestdout = sys.stdout fp = six.StringIO() try: @@ -109,4 +117,5 @@ def capturestdout(f, *args, **kwargs): sys.stdout = savestdout return fp.getvalue() + # End of file diff --git a/src/diffpy/srfit/util/__init__.py b/src/diffpy/srfit/util/__init__.py index dd586190..c26dd72e 100644 --- a/src/diffpy/srfit/util/__init__.py +++ b/src/diffpy/srfit/util/__init__.py @@ -17,7 +17,7 @@ Utilities and constants used throughout SrFit. """ -_DASHEDLINE = 78 * '-' +_DASHEDLINE = 78 * "-" def sortKeyForNumericString(s): @@ -41,12 +41,13 @@ def sortKeyForNumericString(s): """ if sortKeyForNumericString._rx is None: import re - sortKeyForNumericString._rx = re.compile(r'(\d+)') + + sortKeyForNumericString._rx = re.compile(r"(\d+)") rx = sortKeyForNumericString._rx - rv = tuple((int(w) if i % 2 else w) - for i, w in enumerate(rx.split(s))) + rv = tuple((int(w) if i % 2 else w) for i, w in enumerate(rx.split(s))) return rv + sortKeyForNumericString._rx = None # End of file diff --git a/src/diffpy/srfit/util/argbinders.py b/src/diffpy/srfit/util/argbinders.py index a49aec02..c2934dde 100644 --- a/src/diffpy/srfit/util/argbinders.py +++ b/src/diffpy/srfit/util/argbinders.py @@ -19,17 +19,14 @@ class bind2nd(object): - - '''Freeze second argument of a callable object to a given constant. - ''' + """Freeze second argument of a callable object to a given constant.""" def __init__(self, func, arg1): - """Freeze the second argument of function func to arg1. - """ + """Freeze the second argument of function func to arg1.""" self.func = func self.arg1 = arg1 return def __call__(self, *args, **kwargs): - boundargs = ((args[0], self.arg1) + args[1:]) + boundargs = (args[0], self.arg1) + args[1:] return self.func(*boundargs, **kwargs) diff --git a/src/diffpy/srfit/util/inpututils.py b/src/diffpy/srfit/util/inpututils.py index e2b06988..aba08b1f 100644 --- a/src/diffpy/srfit/util/inpututils.py +++ b/src/diffpy/srfit/util/inpututils.py @@ -41,11 +41,12 @@ def inputToString(inpt): # TODO remove handling of string input accept only file or filename # FIXME check for typos in the file name elif os.path.exists(inpt) or (len(inpt) < 80 and inpt.count("\n") == 0): - with open(inpt, 'r') as infile: + with open(inpt, "r") as infile: inptstr = infile.read() else: inptstr = inpt return inptstr + # End of file diff --git a/src/diffpy/srfit/util/nameutils.py b/src/diffpy/srfit/util/nameutils.py index ddfe27a2..4f6cf326 100644 --- a/src/diffpy/srfit/util/nameutils.py +++ b/src/diffpy/srfit/util/nameutils.py @@ -19,7 +19,7 @@ import re -reident = re.compile(r'^[a-zA-Z_]\w*$') +reident = re.compile(r"^[a-zA-Z_]\w*$") def isIdentifier(s): @@ -27,7 +27,8 @@ def isIdentifier(s): From http://code.activestate.com/recipes/413487/ """ - if reident.match(s) is None: return False + if reident.match(s) is None: + return False return True @@ -38,7 +39,8 @@ def validateName(name): """ # Check that the name is valid if not isIdentifier(name): - raise ValueError("Name '%s' is not a valid identifier"%name) + raise ValueError("Name '%s' is not a valid identifier" % name) return + # End of file diff --git a/src/diffpy/srfit/util/observable.py b/src/diffpy/srfit/util/observable.py index 9bb88024..dc671409 100644 --- a/src/diffpy/srfit/util/observable.py +++ b/src/diffpy/srfit/util/observable.py @@ -39,7 +39,6 @@ class Observable(object): """ - def notify(self, other=()): """ Notify all observers @@ -51,7 +50,6 @@ def notify(self, other=()): callable(semaphors) return - # callback management def addObserver(self, callable): """ @@ -61,7 +59,6 @@ def addObserver(self, callable): self._observers.add(f) return - def removeObserver(self, callable): """ Remove callable from the set of observers @@ -70,7 +67,6 @@ def removeObserver(self, callable): self._observers.remove(f) return - def hasObserver(self, callable): """ True if `callable` is present in the set of observers. @@ -79,17 +75,18 @@ def hasObserver(self, callable): rv = f in self._observers return rv - # meta methods def __init__(self, **kwds): super(Observable, self).__init__(**kwds) self._observers = set() return + # end of class Observable # Local helpers -------------------------------------------------------------- + def _fbRemoveObserver(fobs, semaphors): # Remove WeakBoundMethod `fobs` from the observers of notifying object. # This is called from Observable.notify when the WeakBoundMethod @@ -98,4 +95,5 @@ def _fbRemoveObserver(fobs, semaphors): observable.removeObserver(fobs) return + # end of file diff --git a/src/diffpy/srfit/util/tagmanager.py b/src/diffpy/srfit/util/tagmanager.py index 585ca336..b702722d 100644 --- a/src/diffpy/srfit/util/tagmanager.py +++ b/src/diffpy/srfit/util/tagmanager.py @@ -42,12 +42,10 @@ def __init__(self): self.silent = True return - def alltags(self): """Get all tags managed by the TagManager.""" return self._tagdict.keys() - def tag(self, obj, *tags): """Tag an object. @@ -64,7 +62,6 @@ def tag(self, obj, *tags): oset.add(obj) return - def untag(self, obj, *tags): """Remove tags from an object. @@ -87,7 +84,6 @@ def untag(self, obj, *tags): return - def tags(self, obj): """Get all tags on an object. @@ -96,7 +92,6 @@ def tags(self, obj): tags = [k for (k, v) in self._tagdict.items() if obj in v] return tags - def hasTags(self, obj, *tags): """Determine if an object has all passed tags. @@ -106,7 +101,6 @@ def hasTags(self, obj, *tags): result = all(obj in s for s in setgen) return result - def union(self, *tags): """Get all objects that have any of the passed tags. @@ -119,7 +113,6 @@ def union(self, *tags): objs = functools.reduce(set.union, setgen) return objs - def intersection(self, *tags): """Get all objects that have all of the passed tags. @@ -131,7 +124,6 @@ def intersection(self, *tags): objs = functools.reduce(set.intersection, setgen) return objs - def verifyTags(self, *tags): """Check that tags are all extant. @@ -146,7 +138,6 @@ def verifyTags(self, *tags): return True - def __getObjectSet(self, tag): """Helper function for getting an object set with given tag. diff --git a/src/diffpy/srfit/util/weakrefcallable.py b/src/diffpy/srfit/util/weakrefcallable.py index 7afac822..92ead114 100644 --- a/src/diffpy/srfit/util/weakrefcallable.py +++ b/src/diffpy/srfit/util/weakrefcallable.py @@ -18,8 +18,8 @@ """ -import weakref import types +import weakref import six @@ -49,7 +49,7 @@ class WeakBoundMethod(object): This is only used for pickling. """ - __slots__ = ('function', 'fallback', '_wref', '_class') + __slots__ = ("function", "fallback", "_wref", "_class") def __init__(self, f, fallback=None): """Create a weak reference wrapper to bound method. @@ -72,7 +72,6 @@ def __init__(self, f, fallback=None): self._wref = weakref.ref(f.__self__) return - def __call__(self, *args, **kwargs): """Call the wrapped method if the weak-referenced object is alive. @@ -98,28 +97,24 @@ def __call__(self, *args, **kwargs): emsg = "Object bound to {} does not exist.".format(self.function) raise ReferenceError(emsg) - # support use of this class in hashed collections def __hash__(self): return hash((self.function, self._wref)) - def __eq__(self, other): - rv = (self.function == other.function and - (self._wref == other._wref or - None is self._wref() is other._wref())) + rv = self.function == other.function and ( + self._wref == other._wref or None is self._wref() is other._wref() + ) return rv - def __ne__(self, other): return not self.__eq__(other) # support pickling of this type def __getstate__(self): - """Return state with a resolved weak reference. - """ + """Return state with a resolved weak reference.""" mobj = self._wref() nm = self.function.__name__ amsg = "Unable to pickle this unbound function by name." @@ -130,10 +125,8 @@ def __getstate__(self): state = (self._class, nm, self.fallback, mobj) return state - def __setstate__(self, state): - """Restore the weak reference in this wrapper upon unpickling. - """ + """Restore the weak reference in this wrapper upon unpickling.""" (self._class, nm, self.fallback, mobj) = state self.function = getattr(self._class, nm) if mobj is None: @@ -144,15 +137,16 @@ def __setstate__(self, state): self._wref = weakref.ref(mobj) return - @staticmethod def __mimic_empty_ref(): return None + # end of class WeakBoundMethod # ---------------------------------------------------------------------------- + def weak_ref(f, fallback=None): """Create weak-reference wrapper to a bound method.