diff --git a/.codecov.yml b/.codecov.yml index 04dd6510..4af5eb24 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -1,34 +1,14 @@ -# codecov can find this file anywhere in the repo, so we don't need to clutter -# the root folder. -#comment: false - -codecov: - notify: - require_ci_to_pass: no - coverage: status: - patch: + project: # more options at https://docs.codecov.com/docs/commit-status default: - target: '70' - if_no_uploads: error - if_not_found: success - if_ci_failed: failure - project: - default: false - library: - target: auto - if_no_uploads: error - if_not_found: success - if_ci_failed: error - paths: '!*/tests/.*' - - tests: - target: 97.9% - paths: '*/tests/.*' - if_not_found: success - -flags: - tests: - paths: - - tests/ + target: auto # use the coverage from the base commit, fail if coverage is lower + threshold: 0% # allow the coverage to drop by + +comment: + layout: " diff, flags, files" + behavior: default + require_changes: false + require_base: false # [true :: must have a base report to post] + require_head: false # [true :: must have a head report to post] + hide_project_coverage: false # [true :: only show coverage on the git diff aka patch coverage] diff --git a/.codespell/ignore_lines.txt b/.codespell/ignore_lines.txt new file mode 100644 index 00000000..07fa7c8c --- /dev/null +++ b/.codespell/ignore_lines.txt @@ -0,0 +1,2 @@ +;; Please include filenames and explanations for each ignored line. +;; See https://docs.openverse.org/meta/codespell.html for docs. diff --git a/.codespell/ignore_words.txt b/.codespell/ignore_words.txt new file mode 100644 index 00000000..e2ee211b --- /dev/null +++ b/.codespell/ignore_words.txt @@ -0,0 +1,24 @@ +;; Please include explanations for each ignored word (lowercase). +;; See https://docs.openverse.org/meta/codespell.html for docs. + +;; abbreviation for "materials" often used in a journal title +mater + +;; Frobenius norm used in np.linalg.norm +fro + +;; "discus" is the name of a software package +discus +DISCUS + +;; chemical elements +Te +Nd + +;; /src/diffpy/structure/parsers/p_pdb.py:100 +;; pdb identifier +CONECT + +;; /src/diffpy/structure/parsers/p_xcfg.py:452 +;; used in a function +BU diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 34ea3e4c..00000000 --- a/.coveragerc +++ /dev/null @@ -1,13 +0,0 @@ -[run] -source = - diffpy.structure -[report] -omit = - */python?.?/* - */site-packages/nose/* - # ignore _version.py and versioneer.py - .*version.* - *_version.py - -exclude_lines = - if __name__ == '__main__': diff --git a/.flake8 b/.flake8 index 2d2cb168..a5105116 100644 --- a/.flake8 +++ b/.flake8 @@ -1,10 +1,12 @@ +# As of now, flake8 does not natively support configuration via pyproject.toml +# https://github.com/microsoft/vscode-flake8/issues/135 [flake8] exclude = .git, __pycache__, build, dist, - doc/source/conf.py + docs/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 diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index de811ba3..00000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -diffpy.structure/_version.py export-subst diff --git a/.github/ISSUE_TEMPLATE/bug_feature.md b/.github/ISSUE_TEMPLATE/bug_feature.md new file mode 100644 index 00000000..b3454deb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_feature.md @@ -0,0 +1,16 @@ +--- +name: Bug Report or Feature Request +about: Report a bug or suggest a new feature! +title: "" +labels: "" +assignees: "" +--- + +### Problem + + + +### Proposed solution diff --git a/.github/ISSUE_TEMPLATE/release_checklist.md b/.github/ISSUE_TEMPLATE/release_checklist.md new file mode 100644 index 00000000..56bcd015 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/release_checklist.md @@ -0,0 +1,46 @@ +--- +name: Release +about: Checklist and communication channel for PyPI and GitHub release +title: "Ready for PyPI/GitHub release" +labels: "release" +assignees: "" +--- + +### PyPI/GitHub rc-release preparation checklist: + +- [ ] All PRs/issues attached to the release are merged. +- [ ] All the badges on the README are passing. +- [ ] License information is verified as correct. If you are unsure, please comment below. +- [ ] Locally rendered documentation contains all appropriate pages, including API references (check no modules are + missing), tutorials, and other human-written text is up-to-date with any changes in the code. +- [ ] Installation instructions in the README, documentation, and the website are updated. +- [ ] Successfully run any tutorial examples or do functional testing with the latest Python version. +- [ ] Grammar and writing quality are checked (no typos). +- [ ] Install `pip install build twine`, run `python -m build` and `twine check dist/*` to ensure that the package can be built and is correctly formatted for PyPI release. + +Please tag the maintainer (e.g., @username) in the comment here when you are ready for the PyPI/GitHub release. Include any additional comments necessary, such as version information and details about the pre-release here: + +### PyPI/GitHub full-release preparation checklist: + +- [ ] Create a new conda environment and install the rc from PyPI (`pip install ==??`) +- [ ] License information on PyPI is correct. +- [ ] Docs are deployed successfully to `https:///`. +- [ ] Successfully run all tests, tutorial examples or do functional testing. + +Please let the maintainer know that all checks are done and the package is ready for full release. + +### conda-forge release preparation checklist: + + + +- [ ] Ensure that the full release has appeared on PyPI successfully. +- [ ] New package dependencies listed in `conda.txt` and `tests.txt` are added to `meta.yaml` in the feedstock. +- [ ] Close any open issues on the feedstock. Reach out to the maintainer if you have questions. +- [ ] Tag the maintainer for conda-forge release. + +### Post-release checklist + + + +- [ ] Run tutorial examples and conduct functional testing using the installation guide in the README. Attach screenshots/results as comments. +- [ ] Documentation (README, tutorials, API references, and websites) is deployed without broken links or missing figures. diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md new file mode 100644 index 00000000..1099d862 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -0,0 +1,15 @@ +### What problem does this PR address? + + + +### What should the reviewer(s) do? + + + + diff --git a/.github/workflows/build-wheel-release-upload.yml b/.github/workflows/build-wheel-release-upload.yml new file mode 100644 index 00000000..caeb09c4 --- /dev/null +++ b/.github/workflows/build-wheel-release-upload.yml @@ -0,0 +1,18 @@ +name: Release (GitHub/PyPI) and Deploy Docs + +on: + workflow_dispatch: + push: + tags: + - "*" # Trigger on all tags initially, but tag and release privilege are verified in _build-wheel-release-upload.yml + +jobs: + release: + uses: scikit-package/release-scripts/.github/workflows/_build-wheel-release-upload.yml@v0 + with: + project: diffpy.structure + c_extension: false + maintainer_GITHUB_username: sbillinge + secrets: + PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} + PAT_TOKEN: ${{ secrets.PAT_TOKEN }} diff --git a/.github/workflows/check-news-item.yml b/.github/workflows/check-news-item.yml new file mode 100644 index 00000000..e5853983 --- /dev/null +++ b/.github/workflows/check-news-item.yml @@ -0,0 +1,12 @@ +name: Check for News + +on: + pull_request_target: + branches: + - main + +jobs: + check-news-item: + uses: scikit-package/release-scripts/.github/workflows/_check-news-item.yml@v0 + with: + project: diffpy.structure diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml deleted file mode 100644 index fd96a710..00000000 --- a/.github/workflows/codecov.yml +++ /dev/null @@ -1,53 +0,0 @@ -name: Gather coverage report and upload to codecov - -on: - push: - branches: - - main - release: - types: - - prereleased - - published - workflow_dispatch: - -defaults: - run: - shell: bash -l {0} - -jobs: - coverage: - runs-on: ubuntu-latest - steps: - - name: Check out diffpy.structure - uses: actions/checkout@v4 - - - name: Initialize miniconda - uses: conda-incubator/setup-miniconda@v3 - with: - activate-environment: test - auto-update-conda: true - environment-file: environment.yml - auto-activate-base: false - - - name: Conda config - run: >- - conda config --set always_yes yes - --set changeps1 no - - - name: Install diffpy.structure and requirements - run: | - conda install --file requirements/run.txt - conda install --file requirements/test.txt - python -m pip install -r requirements/pip.txt - python -m pip install . --no-deps - - - name: Validate diffpy.structure - run: | - coverage run -m pytest -vv -s - coverage report -m - codecov - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4 - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index df2b392f..00000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Build and Deploy Documentation - -on: - release: - types: - - published - workflow_dispatch: - -defaults: - run: - shell: bash -l {0} - -jobs: - docs: - runs-on: ubuntu-latest - steps: - - name: Check out diffpy.structure - uses: actions/checkout@v4 - - - name: Initialize miniconda - uses: conda-incubator/setup-miniconda@v3 - with: - activate-environment: build - auto-update-conda: true - environment-file: environment.yml - auto-activate-base: false - - - name: Conda config - run: >- - conda config --set always_yes yes - --set changeps1 no - - - name: Install diffpy.structure and build requirements - run: | - conda install --file requirements/build.txt - conda install --file requirements/run.txt - conda install --file requirements/docs.txt - python -m pip install -r requirements/pip.txt - python -m pip install . --no-deps - - - name: build documents - run: make -C doc html - - - name: Deploy - uses: peaceiris/actions-gh-pages@v4 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./doc/build/html diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index 33ece6cf..00000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: Test - -on: - push: - branches: - - main - pull_request: - workflow_dispatch: - -defaults: - run: - shell: bash -l {0} - -jobs: - validate: - runs-on: ubuntu-latest - steps: - - name: Check out diffpy.structure - uses: actions/checkout@v4 - - - name: Initialize miniconda - uses: conda-incubator/setup-miniconda@v3 - with: - activate-environment: test - auto-update-conda: true - environment-file: environment.yml - auto-activate-base: false - - - name: Conda config - run: >- - conda config --set always_yes yes - --set changeps1 no - - - name: Install diffpy.structure and requirements - run: | - conda install --file requirements/run.txt - conda install --file requirements/test.txt - python -m pip install -r requirements/pip.txt - python -m pip install . --no-deps - - - name: Validate diffpy.structure - run: python -m pytest diff --git a/.github/workflows/matrix-and-codecov-on-merge-to-main.yml b/.github/workflows/matrix-and-codecov-on-merge-to-main.yml new file mode 100644 index 00000000..235c9f71 --- /dev/null +++ b/.github/workflows/matrix-and-codecov-on-merge-to-main.yml @@ -0,0 +1,21 @@ +name: CI + +on: + push: + branches: + - main + release: + types: + - prereleased + - published + workflow_dispatch: + +jobs: + matrix-coverage: + uses: scikit-package/release-scripts/.github/workflows/_matrix-and-codecov-on-merge-to-main.yml@v0 + with: + project: diffpy.structure + c_extension: false + headless: false + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/publish-docs-on-release.yml b/.github/workflows/publish-docs-on-release.yml new file mode 100644 index 00000000..461e8ac3 --- /dev/null +++ b/.github/workflows/publish-docs-on-release.yml @@ -0,0 +1,12 @@ +name: Deploy Documentation on Release + +on: + workflow_dispatch: + +jobs: + docs: + uses: scikit-package/release-scripts/.github/workflows/_publish-docs-on-release.yml@v0 + with: + project: diffpy.structure + c_extension: false + headless: false diff --git a/.github/workflows/tests-on-pr.yml b/.github/workflows/tests-on-pr.yml new file mode 100644 index 00000000..1ac611fb --- /dev/null +++ b/.github/workflows/tests-on-pr.yml @@ -0,0 +1,15 @@ +name: Tests on PR + +on: + pull_request: + workflow_dispatch: + +jobs: + tests-on-pr: + uses: scikit-package/release-scripts/.github/workflows/_tests-on-pr.yml@v0 + with: + project: diffpy.structure + c_extension: false + headless: false + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.gitignore b/.gitignore index a25212ea..099e2948 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ __pycache__/ .Python env/ build/ +_build/ develop-eggs/ dist/ downloads/ @@ -90,10 +91,3 @@ target/ # Ipython Notebook .ipynb_checkpoints - -# version information -setup.cfg -/src/diffpy/*/version.cfg - -# Rever -rever/ diff --git a/.isort.cfg b/.isort.cfg index e0926f42..7ce0fb1f 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -1,4 +1,5 @@ [settings] +# Keep import statement below line_length character limit line_length = 115 multi_line_output = 3 include_trailing_comma = True diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c4588061..0e4a84d1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,14 +1,14 @@ default_language_version: - python: python3 + 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 + 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 @@ -16,7 +16,10 @@ repos: - id: check-yaml - id: end-of-file-fixer - id: trailing-whitespace - exclude: '\.(rst|txt)$' + - id: check-case-conflict + - id: check-merge-conflict + - id: check-toml + - id: check-added-large-files - repo: https://github.com/psf/black rev: 24.4.2 hooks: @@ -41,3 +44,23 @@ repos: name: Prevent Commit to Main Branch args: ["--branch", "main"] stages: [pre-commit] + - repo: https://github.com/codespell-project/codespell + rev: v2.3.0 + hooks: + - id: codespell + additional_dependencies: + - tomli + # prettier - multi formatter for .json, .yml, and .md files + - repo: https://github.com/pre-commit/mirrors-prettier + rev: f12edd9c7be1c20cfa42420fd0e6df71e42b51ea # frozen: v4.0.0-alpha.8 + hooks: + - id: prettier + additional_dependencies: + - "prettier@^3.2.4" + # docformatter - PEP 257 compliant docstring formatter + - repo: https://github.com/s-weigand/docformatter + rev: 5757c5190d95e5449f102ace83df92e7d3b06c6c + hooks: + - id: docformatter + additional_dependencies: [tomli] + args: [--in-place, --config, ./pyproject.toml] diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 00000000..aaa88895 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,13 @@ +version: 2 + +build: + os: "ubuntu-22.04" + tools: + python: "latest" + +python: + install: + - requirements: requirements/docs.txt + +sphinx: + configuration: docs/source/conf.py diff --git a/AUTHORS.rst b/AUTHORS.rst index 9f6a419f..1abf16be 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -1,6 +1,7 @@ Authors ======= +Billinge Group and community contributors, Pavol Juhas, Christopher L. Farrow, Xiaohao Yang, diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 0fde0ea2..66a1a4b8 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,9 +1,71 @@ ============= -Release Notes +Release notes ============= .. current developments +3.3.1 +===== + +**Added:** + +* Spelling check via Codespell in pre-commit +* Coverage report in each PR + +**Changed:** + +* Use the names CODE-OF-CONDUCT.rst, docs and requirements/tests.txt according to the new group standard. + +**Fixed:** + +* Let ``diffpy.structure`` pass the tests with ``pycifrw`` installed from ``PyPI``. + + +3.3.0 +===== + +**Added:** + +* Support for Python 3.13 + +**Deprecated:** + +* Support for Python 3.10 + + +3.2.3 +===== + +**Added:** + +* Use GitHub Actions to build, release, upload to PyPI +* Added issue template for PyPI/GitHub release +* Include GitHub Issues templates for bug report and feature request + +**Fixed:** + +* Add getting started section and re-arrange install success check instructions +* Added terminal script for transtru app in pyproject.toml +* Changed requires-python to align with classifiers + + +3.2.2 +===== + +**Added:** + +* Unit test for version.py +* support for numpy >=2.0 + +**Fixed:** + +* tests folder at the root of the repo +* Add pip dependencies under pip.txt and conda dependencies under conda.txt +* element/label itemsize to 5 in _linkAtomAttribute to support numpy >=2.0 +* Recookiecut package to the group standard + + + 3.2.1 ===== diff --git a/CODE_OF_CONDUCT.rst b/CODE-OF-CONDUCT.rst similarity index 98% rename from CODE_OF_CONDUCT.rst rename to CODE-OF-CONDUCT.rst index ff9c3561..e8199ca5 100644 --- a/CODE_OF_CONDUCT.rst +++ b/CODE-OF-CONDUCT.rst @@ -8,7 +8,7 @@ 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, +identity and expression, level of experience, education, socioeconomic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. diff --git a/LICENSE_DANSE.rst b/LICENSE-DANSE.rst similarity index 98% rename from LICENSE_DANSE.rst rename to LICENSE-DANSE.rst index c05648e1..d56af619 100644 --- a/LICENSE_DANSE.rst +++ b/LICENSE-DANSE.rst @@ -9,13 +9,13 @@ Copyright 2006-2007, Board of Trustees of Michigan State University, Copyright 2008-2012, The Trustees of Columbia University in the City of New York. (Copyright holder indicated in each source file). -Copyright (c) 2024, The Trustees of Columbia University in the City of New York. +Copyright (c) 2024, The Trustees of Columbia University in the City of New York. All rights reserved. For more information please visit the project web-page: http://www.diffpy.org/ - + or email Prof. Simon Billinge at sb2896@columbia.edu Redistribution and use in source and binary forms, with or without diff --git a/LICENSE_pymmlib.rst b/LICENSE-pymmlib.rst similarity index 99% rename from LICENSE_pymmlib.rst rename to LICENSE-pymmlib.rst index e0b82c94..ef484f5a 100644 --- a/LICENSE_pymmlib.rst +++ b/LICENSE-pymmlib.rst @@ -1,5 +1,5 @@ .. code-block:: text - + The Artistic License 2.0 Copyright (c) 2000-2006, The Perl Foundation. diff --git a/LICENSE.rst b/LICENSE.rst index f1fe010e..1f91b0ba 100644 --- a/LICENSE.rst +++ b/LICENSE.rst @@ -15,7 +15,7 @@ Copyright (c) 2014, Australian Synchrotron Research Program Inc., ("ASRP") Copyright (c) 2014-2019, Brookhaven Science Associates, Brookhaven National Laboratory -Copyright (c) 2024, The Trustees of Columbia University in the City of New York. +Copyright (c) 2024-2025, The Trustees of Columbia University in the City of New York. All rights reserved. The "DiffPy-CMI" is distributed subject to the following license conditions: diff --git a/MANIFEST.in b/MANIFEST.in index 3bcdfb4f..f1a78eec 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,14 +1,12 @@ -include AUTHORS.rst -include LICENSE -include README.rst -include requirements.txt - -recursive-exclude * __pycache__ -recursive-exclude * *.py[co] - -recursive-include docs *.rst conf.py Makefile make.bat - -include diffpy.structure/version.py - -# If including data files in the package, add them like: -# include path/to/data_file +graft src +graft tests +graft requirements + +include AUTHORS.rst LICENSE*.rst README.rst + +# Exclude all bytecode files and __pycache__ directories +global-exclude *.py[cod] # Exclude all .pyc, .pyo, and .pyd files. +global-exclude .DS_Store # Exclude Mac filesystem artifacts. +global-exclude __pycache__ # Exclude Python cache directories. +global-exclude .git* # Exclude git files and directories. +global-exclude .idea # Exclude PyCharm project settings. diff --git a/README.rst b/README.rst index 5dd3a227..694315b7 100644 --- a/README.rst +++ b/README.rst @@ -8,15 +8,15 @@ :target: https://diffpy.github.io/diffpy.structure :height: 100px -|PyPi| |Forge| |PythonVersion| |PR| +|PyPI| |Forge| |PythonVersion| |PR| |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.structure/actions/workflows/main.yml/badge.svg - :target: https://github.com/diffpy/diffpy.structure/actions/workflows/main.yml +.. |CI| image:: https://github.com/diffpy/diffpy.structure/actions/workflows/matrix-and-codecov-on-merge-to-main.yml/badge.svg + :target: https://github.com/diffpy/diffpy.structure/actions/workflows/matrix-and-codecov-on-merge-to-main.yml .. |Codecov| image:: https://codecov.io/gh/diffpy/diffpy.structure/branch/main/graph/badge.svg :target: https://codecov.io/gh/diffpy/diffpy.structure @@ -26,7 +26,7 @@ .. |PR| image:: https://img.shields.io/badge/PR-Welcome-29ab47ff -.. |PyPi| image:: https://img.shields.io/pypi/v/diffpy.structure +.. |PyPI| image:: https://img.shields.io/pypi/v/diffpy.structure :target: https://pypi.org/project/diffpy.structure/ .. |PythonVersion| image:: https://img.shields.io/pypi/pyversions/diffpy.structure @@ -47,6 +47,7 @@ of symmetry constraints for atom positions and displacement parameters. diffpy.structure includes definitions of all space groups in over 500 symmetry settings. + For more information about the diffpy.structure library, please consult our `online documentation `_. Citation @@ -77,20 +78,18 @@ To add "conda-forge" to the conda channels, run the following in a terminal. :: We want to install our packages in a suitable conda environment. The following creates and activates a new environment named ``diffpy.structure_env`` :: - conda create -n diffpy.structure_env python=3 + conda create -n diffpy.structure_env diffpy.structure conda activate diffpy.structure_env -Then, to fully install ``diffpy.structure`` in our active environment, run :: - - conda install diffpy.structure +To confirm that the installation was successful, type :: -Another option is to use ``pip`` to download and install the latest release from -`Python Package Index `_. -To install using ``pip`` into your ``diffpy.structure_env`` environment, we will also have to install dependencies :: + python -c "import diffpy.structure; print(diffpy.structure.__version__)" - pip install -r https://raw.githubusercontent.com/diffpy/diffpy.structure/main/requirements/run.txt +The output should print the latest version displayed on the badges above. -and then install the package :: +If the above does not work, you can use ``pip`` to download and install the latest release from +`Python Package Index `_. +To install using ``pip`` into your ``diffpy.structure_env`` environment, type :: pip install diffpy.structure @@ -100,12 +99,17 @@ and run the following :: pip install . +Getting Started +--------------- + +You may consult our `online documentation `_ for tutorials and API references. + Support and Contribute ---------------------- `Diffpy user group `_ is the discussion forum for general questions and discussions about the use of diffpy.structure. Please join the diffpy.structure users community by joining the Google group. The diffpy.structure project welcomes your expertise and enthusiasm! -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 `_. +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 `_. Feel free to fork the project and contribute. To install diffpy.structure in a development mode, with its sources being directly used by Python @@ -128,7 +132,7 @@ trying to commit again. Improvements and fixes are always appreciated. -Before contribuing, please read our `Code of Conduct `_. +Before contributing, please read our `Code of Conduct `_. Acknowledgement --------------- @@ -139,6 +143,8 @@ originate from the `pymmlib project `_. Less common settings of space groups were generating using the `Computational Crystallography Toolbox `_. +``diffpy.structure`` is built and maintained with `scikit-package `_. + Contact ------- diff --git a/devutils/makesdist b/devutils/makesdist deleted file mode 100755 index dccfaa99..00000000 --- a/devutils/makesdist +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env python - -"""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 glob -import gzip -import os -import subprocess -import sys -import tarfile - -from setup import FALLBACK_VERSION, versiondata - -BASEDIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) -sys.path.insert(0, BASEDIR) - -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) -inform("[done]\n") - -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") - - -def fixtarinfo(tinfo): - tinfo.uid = tinfo.gid = 0 - tinfo.uname = tinfo.gname = "root" - tinfo.mtime = timestamp - tinfo.mode &= ~0o022 - return tinfo - - -inform("Filter %s --> %s.gz " % (2 * (os.path.basename(tarname),))) -for ti in tfin: - tfout.addfile(fixtarinfo(ti), tfin.extractfile(ti)) - -tfin.close() -os.remove(tarname) -inform("[done]\n") diff --git a/devutils/sgtbx_extra_groups.py b/devutils/sgtbx_extra_groups.py index 4cab28c2..1c718fa8 100644 --- a/devutils/sgtbx_extra_groups.py +++ b/devutils/sgtbx_extra_groups.py @@ -1,10 +1,11 @@ #!/usr/bin/env python -"""Quick and extremely dirty script for generating code for SpaceGroup that -are defined in cctbx, but not in mmLib. It was used to generate module -sgtbxspacegroups. +"""Quick and extremely dirty script for generating code for SpaceGroup +that are defined in cctbx, but not in mmLib. It was used to generate +module sgtbxspacegroups. -This is a utility script that should not be included with code distribution. +This is a utility script that should not be included with code +distribution. Not to be included with code distributions. """ @@ -40,7 +41,8 @@ def tupleToSGArray(tpl): def mmSpaceGroupFromSymbol(symbol): - """Construct SpaceGroup instance from a string symbol using sgtbx data.""" + """Construct SpaceGroup instance from a string symbol using sgtbx + data.""" sginfo = sgtbx.space_group_info(symbol) symop_list = [] symop_list = getSymOpList(sginfo.group()) diff --git a/doc/source/license.rst b/doc/source/license.rst deleted file mode 100644 index cfab61c2..00000000 --- a/doc/source/license.rst +++ /dev/null @@ -1,39 +0,0 @@ -: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/Makefile b/docs/Makefile similarity index 100% rename from doc/Makefile rename to docs/Makefile diff --git a/doc/make.bat b/docs/make.bat similarity index 100% rename from doc/make.bat rename to docs/make.bat diff --git a/doc/manual/Makefile b/docs/manual/Makefile similarity index 100% rename from doc/manual/Makefile rename to docs/manual/Makefile diff --git a/doc/manual/requirements.txt b/docs/manual/requirements.txt similarity index 100% rename from doc/manual/requirements.txt rename to docs/manual/requirements.txt diff --git a/doc/source/_static/.placeholder b/docs/source/_static/.placeholder similarity index 100% rename from doc/source/_static/.placeholder rename to docs/source/_static/.placeholder diff --git a/doc/source/api/diffpy.structure.apps.rst b/docs/source/api/diffpy.structure.apps.rst similarity index 100% rename from doc/source/api/diffpy.structure.apps.rst rename to docs/source/api/diffpy.structure.apps.rst diff --git a/doc/source/api/diffpy.structure.expansion.rst b/docs/source/api/diffpy.structure.expansion.rst similarity index 100% rename from doc/source/api/diffpy.structure.expansion.rst rename to docs/source/api/diffpy.structure.expansion.rst diff --git a/doc/source/api/diffpy.structure.parsers.rst b/docs/source/api/diffpy.structure.parsers.rst similarity index 100% rename from doc/source/api/diffpy.structure.parsers.rst rename to docs/source/api/diffpy.structure.parsers.rst diff --git a/doc/source/api/diffpy.structure.rst b/docs/source/api/diffpy.structure.rst similarity index 100% rename from doc/source/api/diffpy.structure.rst rename to docs/source/api/diffpy.structure.rst diff --git a/doc/source/conf.py b/docs/source/conf.py similarity index 89% rename from doc/source/conf.py rename to docs/source/conf.py index d3af3e37..15ccfef6 100644 --- a/doc/source/conf.py +++ b/docs/source/conf.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- # -# diffpy.structure documentation build configuration file, created by +# diffpy.structure documentation build configuration file, created by # noqa: E501 # sphinx-quickstart on Thu Jan 30 15:49:41 2014. # # This file is execfile()d with the current directory set to its @@ -18,17 +18,21 @@ from importlib.metadata import version from pathlib import Path -autodoc_mock_imports = ["importlib.metadata"] +# Attempt to import the version dynamically from GitHub tag. +try: + fullversion = version("diffpy.structure") +except Exception: + fullversion = "No version found. The correct version will appear in the released version." # noqa: E501 # 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. +# documentation root, use Path().resolve() to make it absolute, like shown here. # noqa: E501 # 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" +ab_authors = "Chris Farrow, Pavol Juhas, Simon Billinge, Billinge Group members" # -- General configuration ------------------------------------------------ @@ -45,11 +49,10 @@ "sphinx.ext.viewcode", "sphinx.ext.intersphinx", "sphinx_rtd_theme", + "sphinx_copybutton", "m2r", ] -autodoc_member_order = "groupwise" - # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] @@ -72,7 +75,6 @@ # |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. @@ -92,6 +94,11 @@ # substitute YEAR in the copyright string copyright = copyright.replace("%Y", year) +# For sphinx_copybutton extension. +# Do not copy "$" for shell commands in code-blocks. +copybutton_prompt_text = r"^\$ " +copybutton_prompt_is_regexp = True + # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ["build"] @@ -120,12 +127,6 @@ # Display all warnings for missing links. nitpicky = True -nitpick_ignore = [ - ("py:class", "array_like"), - ("py:class", "Parser"), - ("py:class", "CifFile"), -] - # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for @@ -133,6 +134,14 @@ # html_theme = "sphinx_rtd_theme" +html_context = { + "display_github": True, + "github_user": "diffpy", + "github_repo": "diffpy.structure", + "github_version": "main", + "conf_py_path": "/docs/source/", +} + # 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. @@ -213,7 +222,7 @@ # Output file base name for HTML help builder. basename = "diffpy.structure".replace(" ", "").replace(".", "") -htmlhelp_basename = basename + "doc" +htmlhelp_basename = basename + "docs" # -- Options for LaTeX output --------------------------------------------- @@ -231,7 +240,13 @@ # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - ("index", "diffpy.structure.tex", "diffpy.structure Documentation", ab_authors, "manual"), + ( + "index", + "diffpy.structure.tex", + "diffpy.structure Documentation", + ab_authors, + "manual", + ), ] # The name of an image file (relative to this directory) to place at the top of @@ -259,7 +274,15 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [("index", "diffpy.structure", "diffpy.structure Documentation", ab_authors, 1)] +man_pages = [ + ( + "index", + "diffpy.structure", + "diffpy.structure Documentation", + ab_authors, + 1, + ) +] # If true, show URL addresses after external links. # man_show_urls = False @@ -297,7 +320,3 @@ # Example configuration for intersphinx: refer to the Python standard library. # intersphinx_mapping = {'http://docs.python.org/': None} -intersphinx_mapping = { - "python": ("https://docs.python.org/3", None), - "numpy": ("https://numpy.org/doc/stable/", None), -} diff --git a/doc/source/diffpy.structure.apps.rst b/docs/source/diffpy.structure.apps.rst similarity index 100% rename from doc/source/diffpy.structure.apps.rst rename to docs/source/diffpy.structure.apps.rst diff --git a/doc/source/diffpy.structure.expansion.rst b/docs/source/diffpy.structure.expansion.rst similarity index 100% rename from doc/source/diffpy.structure.expansion.rst rename to docs/source/diffpy.structure.expansion.rst diff --git a/doc/source/diffpy.structure.parsers.rst b/docs/source/diffpy.structure.parsers.rst similarity index 100% rename from doc/source/diffpy.structure.parsers.rst rename to docs/source/diffpy.structure.parsers.rst diff --git a/docs/source/img/.placeholder b/docs/source/img/.placeholder new file mode 100644 index 00000000..e69de29b diff --git a/doc/source/index.rst b/docs/source/index.rst similarity index 94% rename from doc/source/index.rst rename to docs/source/index.rst index 4fabbaa1..46e3b737 100644 --- a/doc/source/index.rst +++ b/docs/source/index.rst @@ -29,6 +29,7 @@ Pavol Juhás, Christopher L. Farrow, Xiaohao Yang, Simon J.L. Billinge. For a detailed list of contributors see https://github.com/diffpy/diffpy.structure/graphs/contributors. +=============== Acknowledgments =============== @@ -38,9 +39,11 @@ Less common settings of space groups were generating using the Computational Crystallography Toolbox, http://cctbx.sourceforge.net. +``diffpy.structure`` is built and maintained with `scikit-package `_. .. index:: citation, reference +========= Reference ========= diff --git a/docs/source/license.rst b/docs/source/license.rst new file mode 100644 index 00000000..00315fc7 --- /dev/null +++ b/docs/source/license.rst @@ -0,0 +1,148 @@ +:tocdepth: -1 + +.. index:: license + +License +####### + +OPEN SOURCE LICENSE AGREEMENT +============================= + +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) 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) 2009-2011, University of Tennessee + +Copyright (c) 2014, Australian Synchrotron Research Program Inc., ("ASRP") + +Copyright (c) 2014-2019, Brookhaven Science Associates, Brookhaven National Laboratory + +Copyright (c) 2024-2025, The Trustees of Columbia University in the City of New York. +All rights reserved. + +The "DiffPy-CMI" is distributed subject to the following license conditions: + +.. code-block:: text + + 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/doc/source/mod_atom.rst b/docs/source/mod-atom.rst similarity index 100% rename from doc/source/mod_atom.rst rename to docs/source/mod-atom.rst diff --git a/doc/source/mod_lattice.rst b/docs/source/mod-lattice.rst similarity index 100% rename from doc/source/mod_lattice.rst rename to docs/source/mod-lattice.rst diff --git a/doc/source/mod_spacegroup.rst b/docs/source/mod-spacegroup.rst similarity index 100% rename from doc/source/mod_spacegroup.rst rename to docs/source/mod-spacegroup.rst diff --git a/doc/source/release.rst b/docs/source/release.rst similarity index 100% rename from doc/source/release.rst rename to docs/source/release.rst diff --git a/docs/source/snippets/.placeholder b/docs/source/snippets/.placeholder new file mode 100644 index 00000000..e69de29b diff --git a/environment.yml b/environment.yml deleted file mode 100644 index c7cd23cd..00000000 --- a/environment.yml +++ /dev/null @@ -1,6 +0,0 @@ -name: diffpy.structure -channels: - - conda-forge -dependencies: - - python=3 - - pip diff --git a/news/folder.rst b/news/dep-warning1.rst similarity index 72% rename from news/folder.rst rename to news/dep-warning1.rst index 63f83284..bd4b2fbd 100644 --- a/news/folder.rst +++ b/news/dep-warning1.rst @@ -1,6 +1,6 @@ **Added:** -* +* Add deprecation warning for ``diffpy.Structure`` import. **Changed:** @@ -16,7 +16,7 @@ **Fixed:** -* tests folder at the root of the repo +* **Security:** diff --git a/news/numpy2.rst b/news/numpy2.rst deleted file mode 100644 index af1631fa..00000000 --- a/news/numpy2.rst +++ /dev/null @@ -1,23 +0,0 @@ -**Added:** - -* support for numpy >=2.0 - -**Changed:** - -* - -**Deprecated:** - -* - -**Removed:** - -* - -**Fixed:** - -* element/label itemsize to 5 in _linkAtomAttribute to support numpy >=2.0 - -**Security:** - -* diff --git a/news/version-test.rst b/news/version-test.rst deleted file mode 100644 index 05c39477..00000000 --- a/news/version-test.rst +++ /dev/null @@ -1,23 +0,0 @@ -**Added:** - -* Unit test for version.py - -**Changed:** - -* - -**Deprecated:** - -* - -**Removed:** - -* - -**Fixed:** - -* - -**Security:** - -* diff --git a/pyproject.toml b/pyproject.toml index 206884bf..46176534 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,15 +6,15 @@ build-backend = "setuptools.build_meta" name = "diffpy.structure" dynamic=['version', 'dependencies'] authors = [ - { name="Simon J.L. Billinge group", email="simon.billinge@gmail.com" }, + { name="Simon Billinge", email="sb2896@columbia.edu" }, ] maintainers = [ - { name="Simon J.L. Billinge group", email="simon.billinge@gmail.com" }, + { name="Simon Billinge", email="sb2896@columbia.edu" }, ] description = "Crystal structure container and parsers for structure formats." -keywords = ['diffpy', 'crystal structure data storage CIF PDB'] +keywords = ['diffpy', 'crystal structure data storage', 'CIF', 'PDB'] readme = "README.rst" -requires-python = ">=3.10" +requires-python = ">=3.11, <3.14" classifiers = [ 'Development Status :: 5 - Production/Stable', 'Environment :: Console', @@ -25,13 +25,16 @@ classifiers = [ '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', + 'Programming Language :: Python :: 3.13', 'Topic :: Scientific/Engineering :: Physics', 'Topic :: Scientific/Engineering :: Chemistry', ] +[project.scripts] +transtru = "diffpy.structure.apps.transtru:main" + [project.urls] Homepage = "https://github.com/diffpy/diffpy.structure/" Issues = "https://github.com/diffpy/diffpy.structure/issues/" @@ -49,7 +52,17 @@ exclude = [] # exclude packages matching these glob patterns (empty by default) namespaces = false # to disable scanning PEP 420 namespaces (true by default) [tool.setuptools.dynamic] -dependencies = {file = ["requirements/run.txt"]} +dependencies = {file = ["requirements/pip.txt"]} + +[tool.codespell] +exclude-file = ".codespell/ignore_lines.txt" +ignore-words = ".codespell/ignore_words.txt" +skip = "*.cif,*.dat" + +[tool.docformatter] +recursive = true +wrap-summaries = 72 +wrap-descriptions = 72 [tool.black] line-length = 115 diff --git a/requirements/build.txt b/requirements/build.txt index f72d870d..e69de29b 100644 --- a/requirements/build.txt +++ b/requirements/build.txt @@ -1,2 +0,0 @@ -python -setuptools diff --git a/requirements/run.txt b/requirements/conda.txt similarity index 87% rename from requirements/run.txt rename to requirements/conda.txt index 5413a934..0fdcecb6 100644 --- a/requirements/run.txt +++ b/requirements/conda.txt @@ -1,2 +1,2 @@ -numpy -pycifrw +numpy +pycifrw diff --git a/requirements/docs.txt b/requirements/docs.txt index ab17b1c8..5f34c6ed 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -1,4 +1,5 @@ sphinx sphinx_rtd_theme +sphinx-copybutton doctr m2r diff --git a/requirements/pip.txt b/requirements/pip.txt index e69de29b..0fdcecb6 100644 --- a/requirements/pip.txt +++ b/requirements/pip.txt @@ -0,0 +1,2 @@ +numpy +pycifrw diff --git a/requirements/test.txt b/requirements/tests.txt similarity index 79% rename from requirements/test.txt rename to requirements/tests.txt index 6f9ccf84..a7277865 100644 --- a/requirements/test.txt +++ b/requirements/tests.txt @@ -2,4 +2,5 @@ flake8 pytest codecov coverage +pytest-cov pytest-env diff --git a/src/diffpy/Structure.py b/src/diffpy/Structure.py deleted file mode 100644 index 1f65df4b..00000000 --- a/src/diffpy/Structure.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# diffpy.structure Complex Modeling Initiative -# (c) 2017 Brookhaven Science Associates, -# Brookhaven National Laboratory. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -"""Support import of old camel-case module names with `DeprecationWarning`. - -The imported camel-case modules are aliases for the current module -instances. Their `__name__` attributes are thus all in lower-case. - -Warning -------- -This module is deprecated and will be removed in the future. -""" - - -import sys - -# install legacy import hooks -import diffpy.structure._legacy_importer - -# replace this module with the new one -sys.modules["diffpy.Structure"] = diffpy.structure - -# End of file diff --git a/src/diffpy/__init__.py b/src/diffpy/__init__.py index ee55ab5f..7ecfc294 100644 --- a/src/diffpy/__init__.py +++ b/src/diffpy/__init__.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ############################################################################## # -# (c) 2024 The Trustees of Columbia University in the City of New York. +# (c) 2024-2025 The Trustees of Columbia University in the City of New York. # All rights reserved. # # File coded by: Billinge Group members and community contributors. @@ -12,12 +12,3 @@ # See LICENSE.rst for license information. # ############################################################################## - -"""Blank namespace package for module diffpy.""" - - -from pkgutil import extend_path - -__path__ = extend_path(__path__, __name__) - -# End of file diff --git a/src/diffpy/structure/__init__.py b/src/diffpy/structure/__init__.py index f8106490..62778b45 100644 --- a/src/diffpy/structure/__init__.py +++ b/src/diffpy/structure/__init__.py @@ -1,10 +1,10 @@ #!/usr/bin/env python ############################################################################## # -# (c) 2024 The Trustees of Columbia University in the City of New York. +# (c) 2024-2025 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: Chris Farrow, Pavol Juhas, Simon Billinge, Billinge Group members. # # See GitHub contributions for a more detailed list of contributors. # https://github.com/diffpy/diffpy.structure/graphs/contributors @@ -12,9 +12,7 @@ # See LICENSE.rst for license information. # ############################################################################## - -""" -Crystal structure container and parsers for structure formats. +"""Crystal structure container and parsers for structure formats. Classes related to the structure of materials: * Atom @@ -35,8 +33,10 @@ * SymmetryError """ -# Interface definitions ------------------------------------------------------ +import sys + +import diffpy.structure as _structure from diffpy.structure.atom import Atom from diffpy.structure.lattice import Lattice from diffpy.structure.parsers import getParser @@ -47,6 +47,28 @@ # package version from diffpy.structure.version import __version__ +# Deprecations ------------------------------------------------------- + + +# @deprecated +# custom deprecator for diffpy.Structure module +class DeprecatedStructureModule: + """Proxy for backward compatibility of diffpy.Structure.""" + + def __getattr__(self, name): + import warnings + + warnings.warn( + "Module 'diffpy.Structure' is deprecated and will be removed in version 4.0. " + "Use 'diffpy.structure' instead.", + DeprecationWarning, + stacklevel=2, + ) + return getattr(_structure, name) + + +sys.modules["diffpy.Structure"] = DeprecatedStructureModule() + # top level routines diff --git a/src/diffpy/structure/_legacy_importer.py b/src/diffpy/structure/_legacy_importer.py index e37a907f..56123c60 100644 --- a/src/diffpy/structure/_legacy_importer.py +++ b/src/diffpy/structure/_legacy_importer.py @@ -12,9 +12,8 @@ # See LICENSE.txt for license information. # ############################################################################## - -""" -Support import of old camel-case module names with DeprecationWarning. +"""Support import of old camel-case module names with +DeprecationWarning. The imported camel-case modules are aliases for the current module instances. Their `__name__` attributes are thus all in lower-case. @@ -61,6 +60,7 @@ def find_spec(self, fullname, path=None, target=None): class MapRenamedStructureModule(importlib.abc.Loader): """Loader for old camel-case module names. + Import the current module and alias it under the old name. """ diff --git a/src/diffpy/structure/apps/__init__.py b/src/diffpy/structure/apps/__init__.py index 6f0249a8..98aa2feb 100644 --- a/src/diffpy/structure/apps/__init__.py +++ b/src/diffpy/structure/apps/__init__.py @@ -12,6 +12,4 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - -"""Script applications that use the `diffpy.structure` package. -""" +"""Script applications that use the `diffpy.structure` package.""" diff --git a/src/diffpy/structure/apps/anyeye.py b/src/diffpy/structure/apps/anyeye.py index fbf549ca..39122fee 100755 --- a/src/diffpy/structure/apps/anyeye.py +++ b/src/diffpy/structure/apps/anyeye.py @@ -12,9 +12,7 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - -""" -Anyeye view structure file in atomeye. +"""Anyeye view structure file in atomeye. Usage: ``anyeye [options] strufile`` @@ -65,7 +63,8 @@ def usage(style=None): - """Show usage info, for ``style=="brief"`` show only first 2 lines.""" + """Show usage info, for ``style=="brief"`` show only first 2 + lines.""" import os.path myname = os.path.basename(sys.argv[0]) @@ -175,7 +174,7 @@ def cleanUp(pd): def parseFormula(formula): - """Parse chemical formula and return a list of elements""" + """Parse chemical formula and return a list of elements.""" # remove all blanks formula = re.sub(r"\s", "", formula) if not re.match("^[A-Z]", formula): @@ -265,7 +264,7 @@ def main(): spawnargs = (pd["viewer"], pd["viewer"], pd["tmpfile"], env) # load strufile in atomeye if pd["watch"]: - signal.signal(signal.SIGCLD, signalHandler) + signal.signal(signal.SIGCHLD, signalHandler) os.spawnlpe(os.P_NOWAIT, *spawnargs) watchStructureFile(pd) else: diff --git a/src/diffpy/structure/apps/transtru.py b/src/diffpy/structure/apps/transtru.py index 86c682db..4c8af03a 100755 --- a/src/diffpy/structure/apps/transtru.py +++ b/src/diffpy/structure/apps/transtru.py @@ -12,7 +12,6 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - """Translate structure file to different format. Usage: ``transtru INFMT..OUTFMT strufile`` @@ -44,7 +43,8 @@ def usage(style=None): - """Show usage info, for ``style=="brief"`` show only first 2 lines.""" + """Show usage info, for ``style=="brief"`` show only first 2 + lines.""" import os.path myname = os.path.basename(sys.argv[0]) diff --git a/src/diffpy/structure/atom.py b/src/diffpy/structure/atom.py index e531780b..beac9e7b 100644 --- a/src/diffpy/structure/atom.py +++ b/src/diffpy/structure/atom.py @@ -12,10 +12,8 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - -""" -Provide class Atom for managing properties of an atom in structure model. -""" +"""Provide class Atom for managing properties of an atom in structure +model.""" import numpy @@ -176,7 +174,8 @@ def msdLat(self, vl): return msd def msdCart(self, vc): - """Calculate mean square displacement along the Cartesian vector. + """Calculate mean square displacement along the Cartesian + vector. Parameters ---------- @@ -252,7 +251,8 @@ def __copy__(self, target=None): @property def xyz_cartn(self): - """numpy.ndarray: Atom position in absolute Cartesian coordinates. + """numpy.ndarray: Atom position in absolute Cartesian + coordinates. This is computed from fractional coordinates `xyz` and the current `lattice` setup. Assignment to *xyz_cartn* or @@ -301,7 +301,8 @@ def anisotropy(self, value): @property def U(self): - """numpy.ndarray : The 3x3 matrix of anisotropic atomic displacements. + """numpy.ndarray : The 3x3 matrix of anisotropic atomic + displacements. For isotropic displacements (when `anisotropy` is ``False``) assignment to *U* uses only the first ``Unew[0, 0]`` element @@ -537,7 +538,8 @@ def __setitem__(self, idx, value): return def __array_wrap__(self, out_arr, context=None, return_scalar=None): - """Ensure math operations on this type yield standard numpy array.""" + """Ensure math operations on this type yield standard numpy + array.""" return out_arr.view(numpy.ndarray) diff --git a/src/diffpy/structure/expansion/__init__.py b/src/diffpy/structure/expansion/__init__.py index faa60ca3..8e6d02c1 100644 --- a/src/diffpy/structure/expansion/__init__.py +++ b/src/diffpy/structure/expansion/__init__.py @@ -12,7 +12,6 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - """Methods and classes for manipulating `Structure` instances. Package content: diff --git a/src/diffpy/structure/expansion/makeellipsoid.py b/src/diffpy/structure/expansion/makeellipsoid.py index 009be577..547096c2 100644 --- a/src/diffpy/structure/expansion/makeellipsoid.py +++ b/src/diffpy/structure/expansion/makeellipsoid.py @@ -12,7 +12,6 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - """Make a spheroid nanoparticle from a template structure.""" from math import ceil @@ -42,8 +41,7 @@ def makeSphere(S, radius): def makeEllipsoid(S, a, b=None, c=None): - """ - Cut a `Structure` out of another one. + """Cut a `Structure` out of another one. Parameters ---------- diff --git a/src/diffpy/structure/expansion/shapeutils.py b/src/diffpy/structure/expansion/shapeutils.py index 0e99df05..16f6c4c3 100644 --- a/src/diffpy/structure/expansion/shapeutils.py +++ b/src/diffpy/structure/expansion/shapeutils.py @@ -12,7 +12,6 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - """Utilities for making shapes.""" @@ -33,7 +32,7 @@ def findCenter(S): """ best = -1 bestd = len(S) - center = [0.5, 0.5, 0.5] # the cannonical center + center = [0.5, 0.5, 0.5] # the canonical center for i in range(len(S)): d = S.lattice.dist(S[i].xyz, center) diff --git a/src/diffpy/structure/expansion/supercell_mod.py b/src/diffpy/structure/expansion/supercell_mod.py index b5760a3b..44d55408 100644 --- a/src/diffpy/structure/expansion/supercell_mod.py +++ b/src/diffpy/structure/expansion/supercell_mod.py @@ -12,9 +12,8 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - -"""This module contains functions for simple `Structure` manipulation. -""" +"""This module contains functions for simple `Structure` +manipulation.""" import numpy @@ -22,8 +21,7 @@ def supercell(S, mno): - """ - Perform supercell expansion for a `Structure`. + """Perform supercell expansion for a `Structure`. New `lattice` parameters are multiplied and fractional coordinates divided by corresponding multiplier. New `Atoms` are grouped with diff --git a/src/diffpy/structure/lattice.py b/src/diffpy/structure/lattice.py index fb51de04..5a623208 100644 --- a/src/diffpy/structure/lattice.py +++ b/src/diffpy/structure/lattice.py @@ -12,9 +12,8 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - -"""Class Lattice stores properties and provides simple operations in lattice -coordinate system. +"""Class Lattice stores properties and provides simple operations in +lattice coordinate system. Attributes ---------- @@ -442,6 +441,7 @@ def setLatBase(self, base): def abcABG(self): """Return the cell parameters in the standard setting. + Returns ------- tuple : @@ -452,6 +452,7 @@ def abcABG(self): def reciprocal(self): """Return the reciprocal lattice of the current lattice. + Returns ------- Lattice diff --git a/src/diffpy/structure/mmlibspacegroups.py b/src/diffpy/structure/mmlibspacegroups.py index faa5ce2d..1acd2662 100644 --- a/src/diffpy/structure/mmlibspacegroups.py +++ b/src/diffpy/structure/mmlibspacegroups.py @@ -3,8 +3,7 @@ # This code is part of the PyMMLib distribution and governed by # its license.Please see the LICENSE_pymmlib file that should have been # included as part of this package. -"""Space groups defined as a part of the pymmlib. -""" +"""Space groups defined as a part of the pymmlib.""" from diffpy.structure.spacegroupmod import ( Rot_mX_mXY_mZ, diff --git a/src/diffpy/structure/parsers/__init__.py b/src/diffpy/structure/parsers/__init__.py index 0d549b80..cb9bd4f8 100644 --- a/src/diffpy/structure/parsers/__init__.py +++ b/src/diffpy/structure/parsers/__init__.py @@ -12,7 +12,6 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - """Conversion plugins for various structure formats. The recognized structure formats are defined by subclassing `StructureParser`, diff --git a/src/diffpy/structure/parsers/p_auto.py b/src/diffpy/structure/parsers/p_auto.py index 745eb5a9..ae0ae05a 100644 --- a/src/diffpy/structure/parsers/p_auto.py +++ b/src/diffpy/structure/parsers/p_auto.py @@ -12,7 +12,6 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - """Parser for automatic file format detection. This Parser does not provide the the `toLines()` method. @@ -54,6 +53,7 @@ def __init__(self, **kw): # parseLines helpers def _getOrderedFormats(self): """Build a list of relevance ordered structure formats. + This only works when `self.filename` has a known extension. """ from diffpy.structure.parsers import inputFormats @@ -77,7 +77,8 @@ def _getOrderedFormats(self): return ofmts def parseLines(self, lines): - """Detect format and create `Structure` instance from a list of lines. + """Detect format and create `Structure` instance from a list of + lines. Set format attribute to the detected file format. @@ -119,7 +120,8 @@ def parse(self, s): return self._wrapParseMethod("parse", s) def parseFile(self, filename): - """Detect format and create Structure instance from an existing file. + """Detect format and create Structure instance from an existing + file. Set format attribute to the detected file format. @@ -144,9 +146,9 @@ def parseFile(self, filename): return self._wrapParseMethod("parseFile", filename) def _wrapParseMethod(self, method, *args, **kwargs): - """A helper evaluator method that try the specified parse method with - each registered structure parser and return the first successful - resul. + """A helper evaluator method that try the specified parse method + with each registered structure parser and return the first + successful result. Structure parsers that match structure file extension are tried first. diff --git a/src/diffpy/structure/parsers/p_cif.py b/src/diffpy/structure/parsers/p_cif.py index 6fba3b44..3d0611ab 100644 --- a/src/diffpy/structure/parsers/p_cif.py +++ b/src/diffpy/structure/parsers/p_cif.py @@ -12,7 +12,6 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - """Parser for basic CIF file format. Attributes @@ -33,6 +32,7 @@ from contextlib import contextmanager import numpy +from CifFile.yapps3_compiled_rt import YappsSyntaxError from diffpy.structure import Atom, Lattice, Structure from diffpy.structure.parsers import StructureParser @@ -267,7 +267,8 @@ def _tr_atom_site_aniso_B_23(a, value): _tr_atom_site_aniso_B_23 = staticmethod(_tr_atom_site_aniso_B_23) def _get_atom_setters(cifloop): - """Static method for finding translators of CifLoop items to data in `Atom` instance. + """Static method for finding translators of CifLoop items to + data in `Atom` instance. Parameters ---------- @@ -408,7 +409,7 @@ def _parseCifDataSource(self, datasource): # stop after reading the first structure if self.stru is not None: break - except (StarError, ValueError, IndexError) as err: + except (YappsSyntaxError, StarError, ValueError, IndexError) as err: exc_type, exc_value, exc_traceback = sys.exc_info() emsg = str(err).strip() e = StructureFormatError(emsg) @@ -416,8 +417,8 @@ def _parseCifDataSource(self, datasource): return self.stru def _parseCifBlock(self, blockname): - """Translate CIF file block, skip blocks without `_atom_site_label`. - Updates data members `stru`, `eau`. + """Translate CIF file block, skip blocks without + `_atom_site_label`. Updates data members `stru`, `eau`. Parameters ---------- @@ -505,7 +506,8 @@ def _parse_atom_site_label(self, block): return def _parse_atom_site_aniso_label(self, block): - """Obtain value of anisotropic thermal displacements from a `CifBlock`. + """Obtain value of anisotropic thermal displacements from a + `CifBlock`. This method updates `U` members of `Atom` instances in `self.stru`. The `labelindex` dictionary has to be defined beforehand. @@ -599,7 +601,8 @@ def _parse_space_group_symop_operation_xyz(self, block): return def _expandAsymmetricUnit(self, block): - """Perform symmetry expansion of `self.stru` using `self.spacegroup`. + """Perform symmetry expansion of `self.stru` using + `self.spacegroup`. This method updates data in `stru` and `eau`. @@ -763,7 +766,8 @@ def toLines(self, stru): def leading_float(s, d=0.0): - """Extract the first float from a string and ignore trailing characters. + """Extract the first float from a string and ignore trailing + characters. Useful for extracting values from "value(std)" syntax. @@ -863,7 +867,8 @@ def getParser(eps=None): @contextmanager def _suppressCifParserOutput(): - """Context manager which suppresses diagnostic messages from CIF parser.""" + """Context manager which suppresses diagnostic messages from CIF + parser.""" from CifFile import yapps3_compiled_rt print_error = yapps3_compiled_rt.print_error diff --git a/src/diffpy/structure/parsers/p_discus.py b/src/diffpy/structure/parsers/p_discus.py index 3ee7e5fd..e8220ca7 100644 --- a/src/diffpy/structure/parsers/p_discus.py +++ b/src/diffpy/structure/parsers/p_discus.py @@ -12,9 +12,7 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - -"""Parser for DISCUS structure format -""" +"""Parser for DISCUS structure format.""" import sys from functools import reduce @@ -25,8 +23,8 @@ class P_discus(StructureParser): - """Parser for DISCUS structure format. The parser chokes - on molecule and generator records. + """Parser for DISCUS structure format. The parser chokes on molecule + and generator records. Attributes ---------- @@ -274,7 +272,7 @@ def _parse_unknown_record(self, words): Raises ------ StructureFormatError - Unkown record. + Unknown record. """ self.ignored_lines.append(self.line) return diff --git a/src/diffpy/structure/parsers/p_pdb.py b/src/diffpy/structure/parsers/p_pdb.py index 6d0f95aa..a7d2d936 100644 --- a/src/diffpy/structure/parsers/p_pdb.py +++ b/src/diffpy/structure/parsers/p_pdb.py @@ -12,7 +12,6 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - """Basic parser for PDB structure format. Note @@ -281,9 +280,8 @@ def cryst1Lines(self, stru): return lines def atomLines(self, stru, idx): - """Build `ATOM` records and possibly `SIGATM`, `ANISOU` or `SIGUIJ` records - for `structure` stru `atom` number aidx. - """ + """Build `ATOM` records and possibly `SIGATM`, `ANISOU` or + `SIGUIJ` records for `structure` stru `atom` number aidx.""" lines = [] a = stru[idx] ad = a.__dict__ diff --git a/src/diffpy/structure/parsers/p_pdffit.py b/src/diffpy/structure/parsers/p_pdffit.py index 692c417f..f0c50bd4 100644 --- a/src/diffpy/structure/parsers/p_pdffit.py +++ b/src/diffpy/structure/parsers/p_pdffit.py @@ -12,9 +12,7 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - -"""Parser for PDFfit structure format -""" +"""Parser for PDFfit structure format.""" import sys from functools import reduce diff --git a/src/diffpy/structure/parsers/p_rawxyz.py b/src/diffpy/structure/parsers/p_rawxyz.py index 65e9588e..24ad293b 100644 --- a/src/diffpy/structure/parsers/p_rawxyz.py +++ b/src/diffpy/structure/parsers/p_rawxyz.py @@ -12,11 +12,10 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - """Parser for raw XYZ file format. -Raw XYZ is a 3 or 4 column text file with cartesian coordinates -of atoms and an optional first column for atom types. +Raw XYZ is a 3 or 4 column text file with cartesian coordinates of atoms +and an optional first column for atom types. """ import sys diff --git a/src/diffpy/structure/parsers/p_xcfg.py b/src/diffpy/structure/parsers/p_xcfg.py index 372e7ba8..ea432a6b 100644 --- a/src/diffpy/structure/parsers/p_xcfg.py +++ b/src/diffpy/structure/parsers/p_xcfg.py @@ -12,7 +12,6 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - """Parser for extended CFG format used by atomeye. Attributes @@ -287,7 +286,8 @@ def parseLines(self, lines): return stru def toLines(self, stru): - """Convert Structure stru to a list of lines in XCFG atomeye format. + """Convert Structure stru to a list of lines in XCFG atomeye + format. Parameters ---------- @@ -424,7 +424,8 @@ def getParser(): def _assign_auxiliaries(a, fields, auxiliaries, no_velocity): - """Assing auxiliary properties for `Atom` object when reading CFG format. + """Assign auxiliary properties for `Atom` object when reading CFG + format. Parameters ---------- diff --git a/src/diffpy/structure/parsers/p_xyz.py b/src/diffpy/structure/parsers/p_xyz.py index cd540a90..5c08f99b 100644 --- a/src/diffpy/structure/parsers/p_xyz.py +++ b/src/diffpy/structure/parsers/p_xyz.py @@ -12,12 +12,11 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## +"""Parser for XYZ file format, where. -"""Parser for XYZ file format, where - - * First line gives number of atoms. - * Second line has optional title. - * Remaining lines contain element, `x, y, z`. +* First line gives number of atoms. +* Second line has optional title. +* Remaining lines contain element, `x, y, z`. """ import sys diff --git a/src/diffpy/structure/parsers/parser_index_mod.py b/src/diffpy/structure/parsers/parser_index_mod.py index 5bb6ba98..5f8c3ec7 100644 --- a/src/diffpy/structure/parsers/parser_index_mod.py +++ b/src/diffpy/structure/parsers/parser_index_mod.py @@ -12,7 +12,6 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - """Index of recognized structure formats, their IO capabilities and associated modules where they are defined. diff --git a/src/diffpy/structure/parsers/structureparser.py b/src/diffpy/structure/parsers/structureparser.py index 2b748664..f785b52e 100644 --- a/src/diffpy/structure/parsers/structureparser.py +++ b/src/diffpy/structure/parsers/structureparser.py @@ -12,9 +12,7 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - -"""Definition of StructureParser, a base class for specific parsers. -""" +"""Definition of StructureParser, a base class for specific parsers.""" class StructureParser(object): diff --git a/src/diffpy/structure/pdffitstructure.py b/src/diffpy/structure/pdffitstructure.py index cc3b66d1..73115db6 100644 --- a/src/diffpy/structure/pdffitstructure.py +++ b/src/diffpy/structure/pdffitstructure.py @@ -12,9 +12,7 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - -"""Definition of PDFFitStructure class derived from Structure -""" +"""Definition of PDFFitStructure class derived from Structure.""" from diffpy.structure.structure import Structure diff --git a/src/diffpy/structure/sgtbxspacegroups.py b/src/diffpy/structure/sgtbxspacegroups.py index 0ba28fc2..30aacfcf 100644 --- a/src/diffpy/structure/sgtbxspacegroups.py +++ b/src/diffpy/structure/sgtbxspacegroups.py @@ -12,9 +12,9 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - -"""Extra space group representations generated using `sgtbx` module from `cctbx`. -Import of this module extends the `SpaceGroupList` in the `SpaceGroups` module. +"""Extra space group representations generated using `sgtbx` module from +`cctbx`. Import of this module extends the `SpaceGroupList` in the +`SpaceGroups` module. Attributes ---------- diff --git a/src/diffpy/structure/spacegroupmod.py b/src/diffpy/structure/spacegroupmod.py index c31b7cae..b14d3023 100644 --- a/src/diffpy/structure/spacegroupmod.py +++ b/src/diffpy/structure/spacegroupmod.py @@ -3,12 +3,11 @@ # This code is part of the PyMMLib distribution and governed by # its license. Please see the LICENSE_pymmlib file that should have been # included as part of this package. -"""Symmetry operations as functions on vectors or arrays. -""" +"""Symmetry operations as functions on vectors or arrays.""" import numpy -# 64 unique rotation matricies +# 64 unique rotation matrices Rot_Z_mY_X = numpy.array([[0.0, 0.0, 1.0], [0.0, -1.0, 0.0], [1.0, 0.0, 0.0]], float) Rot_Y_mX_mZ = numpy.array([[0.0, 1.0, 0.0], [-1.0, 0.0, 0.0], [0.0, 0.0, -1.0]], float) Rot_XmY_X_mZ = numpy.array([[1.0, -1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, -1.0]], float) @@ -144,7 +143,8 @@ def __str__(self): return x def __call__(self, vec): - """Return symmetry-related position for the specified coordinates. + """Return symmetry-related position for the specified + coordinates. Parameters ---------- @@ -302,7 +302,8 @@ def check_group_name(self, name): return False def iter_equivalent_positions(self, vec): - """Generate symmetry equivalent positions for the specified position. + """Generate symmetry equivalent positions for the specified + position. The initial position must be in fractional coordinates and so are the symmetry equivalent positions yielded by iteration. diff --git a/src/diffpy/structure/spacegroups.py b/src/diffpy/structure/spacegroups.py index 414d56e5..a5d33372 100644 --- a/src/diffpy/structure/spacegroups.py +++ b/src/diffpy/structure/spacegroups.py @@ -12,7 +12,6 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - """Space group classes and definitions from mmLib and sgtbx. Attributes @@ -693,7 +692,8 @@ def GetSpaceGroup(sgid): def IsSpaceGroupIdentifier(sgid): - """Check if identifier can be used as an argument to `GetSpaceGroup`. + """Check if identifier can be used as an argument to + `GetSpaceGroup`. Returns ------- @@ -768,6 +768,7 @@ def _hashSymOpList(symops): def _buildSGLookupTable(): """Rebuild space group lookup table from the `SpaceGroupList` data. + This routine updates the global `_sg_lookup_table` dictionary. """ _sg_lookup_table.clear() @@ -809,7 +810,8 @@ def _buildSGLookupTable(): def _getSGHashLookupTable(): - """Return lookup table of symop hashes to standard `SpaceGroup` objects.""" + """Return lookup table of symop hashes to standard `SpaceGroup` + objects.""" if _sg_hash_lookup_table: return _sg_hash_lookup_table for sg in SpaceGroupList: diff --git a/src/diffpy/structure/structure.py b/src/diffpy/structure/structure.py index f0cb515c..1193b929 100644 --- a/src/diffpy/structure/structure.py +++ b/src/diffpy/structure/structure.py @@ -12,9 +12,7 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - -"""This module defines class `Structure`. -""" +"""This module defines class `Structure`.""" import codecs import copy as copymod @@ -29,7 +27,8 @@ class Structure(list): - """Define group of atoms in a specified lattice. Structure --> group of atoms. + """Define group of atoms in a specified lattice. Structure --> group + of atoms. `Structure` class is inherited from Python `list`. It contains a list of `Atom` instances. `Structure` overloads `setitem` and `setslice` @@ -184,7 +183,8 @@ def assignUniqueLabels(self): return def distance(self, aid0, aid1): - """Calculate distance between 2 `Atoms`, no periodic boundary conditions. + """Calculate distance between 2 `Atoms`, no periodic boundary + conditions. Parameters ---------- @@ -208,8 +208,7 @@ def distance(self, aid0, aid1): return self.lattice.dist(a0.xyz, a1.xyz) def angle(self, aid0, aid1, aid2): - """ - The bond angle at the second of three `Atoms` in degrees. + """The bond angle at the second of three `Atoms` in degrees. Parameters ---------- @@ -236,7 +235,7 @@ def angle(self, aid0, aid1, aid2): return self.lattice.angle(u10, u12) def placeInLattice(self, new_lattice): - """place structure into `new_lattice` coordinate system. + """Place structure into `new_lattice` coordinate system. Sets `lattice` to `new_lattice` and recalculate fractional coordinates of all `Atoms` so their absolute positions remain the same. @@ -353,7 +352,8 @@ def write(self, filename, format): return def writeStr(self, format): - """return string representation of the structure in specified format. + """Return string representation of the structure in specified + format. Note ---- @@ -368,14 +368,16 @@ def writeStr(self, format): return s def tolist(self): - """Return `Atoms` in this `Structure` as a standard Python list.""" + """Return `Atoms` in this `Structure` as a standard Python + list.""" rv = [a for a in self] return rv # Overloaded list Methods and Operators ---------------------------------- def append(self, a, copy=True): - """Append `Atom` to a structure and update its `lattice` attribute. + """Append `Atom` to a structure and update its `lattice` + attribute. Parameters ---------- @@ -451,7 +453,7 @@ def __getitem__(self, idx): Parameters ---------- - idx : int ot str ot Iterable + idx : int or str or Iterable `Atom` identifier. When integer use standard list lookup. For iterables use numpy lookup, this supports integer or boolean flag arrays. For string or string-containing iterables @@ -564,7 +566,7 @@ def _fixlat(a): keep = set(super(Structure, self).__getitem__(idx)) v1 = (a if a in keep else Atom(a) for a in value) vfinal = filter(_fixlat, v1) - # handle scalar assingment + # handle scalar assignment else: vfinal = Atom(value) if copy else value vfinal.lattice = self.lattice @@ -572,7 +574,8 @@ def _fixlat(a): return def __add__(self, other): - """Return new `Structure` object with appended `Atoms` from other. + """Return new `Structure` object with appended `Atoms` from + other. Parameters ---------- @@ -605,7 +608,8 @@ def __iadd__(self, other): return self def __sub__(self, other): - """Return new `Structure` that has `Atoms` from the other removed. + """Return new `Structure` that has `Atoms` from the other + removed. Parameters ---------- @@ -640,8 +644,8 @@ def __isub__(self, other): return self def __mul__(self, n): - """Return new `Structure` with n-times concatenated `Atoms` from self. - `Atoms` and `lattice` in the new structure are all copies. + """Return new `Structure` with n-times concatenated `Atoms` from + self. `Atoms` and `lattice` in the new structure are all copies. Parameters ---------- @@ -661,8 +665,8 @@ def __mul__(self, n): __rmul__ = __mul__ def __imul__(self, n): - """Concatenate this `Structure` to n-times more `Atoms`. - For positive multiple the current `Atom` objects remain at the + """Concatenate this `Structure` to n-times more `Atoms`. For + positive multiple the current `Atom` objects remain at the beginning of this `Structure`. Parameters @@ -859,7 +863,8 @@ def _get_composition(self): # Private Methods -------------------------------------------------------- def __emptySharedStructure(self): - """Return empty `Structure` with standard attributes same as in self.""" + """Return empty `Structure` with standard attributes same as in + self.""" rv = Structure() rv.__dict__.update([(k, getattr(self, k)) for k in rv.__dict__]) return rv diff --git a/src/diffpy/structure/structureerrors.py b/src/diffpy/structure/structureerrors.py index c930b9b7..f9a2aaec 100644 --- a/src/diffpy/structure/structureerrors.py +++ b/src/diffpy/structure/structureerrors.py @@ -12,9 +12,7 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - -"""Exceptions used in Structure package. -""" +"""Exceptions used in Structure package.""" class StructureFormatError(Exception): diff --git a/src/diffpy/structure/symmetryutilities.py b/src/diffpy/structure/symmetryutilities.py index b58e7c88..94a08421 100644 --- a/src/diffpy/structure/symmetryutilities.py +++ b/src/diffpy/structure/symmetryutilities.py @@ -12,9 +12,8 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - -"""Symmetry utility functions such as expansion of asymmetric unit, -and generation of positional constraints. +"""Symmetry utility functions such as expansion of asymmetric unit, and +generation of positional constraints. Attributes ---------- @@ -132,8 +131,8 @@ def isconstantFormula(s): class _Position2Tuple(object): - """Create callable object that converts fractional coordinates to - a tuple of integers with given precision. For presision close to zero + """Create callable object that converts fractional coordinates to a + tuple of integers with given precision. For presision close to zero it will return a tuples of double. Note @@ -148,7 +147,7 @@ class _Position2Tuple(object): Attributes ---------- eps : float - Cutoff for equivalent coordinates. When two coordiantes map to the + Cutoff for equivalent coordinates. When two coordinates map to the same tuple, they are closer than `eps`. """ @@ -417,7 +416,8 @@ class GeneratorSite(object): ], dtype=float, ) - """numpy.ndarray: 6x3x3 array of independent components of U matrices.""" + """numpy.ndarray: 6x3x3 array of independent components of U + matrices.""" idx2Usymbol = {0: "U11", 1: "U12", 2: "U13", 3: "U12", 4: "U22", 5: "U23", 6: "U13", 7: "U23", 8: "U33"} """dict: Mapping of index to standard U symbol.""" @@ -467,7 +467,8 @@ def __init__(self, spacegroup, xyz, Uij=numpy.zeros((3, 3)), sgoffset=[0, 0, 0], return def signedRatStr(self, x): - """Convert floating point number to signed rational representation. + """Convert floating point number to signed rational + representation. Possible fractional are multiples of 1/3, 1/6, 1/7, 1/9, if these are not close, return `%+g` format. @@ -495,6 +496,7 @@ def signedRatStr(self, x): def _findNullSpace(self): """Calculate `self.null_space` from `self.invariants`. + Try to represent `self.null_space` using small integers. """ R0 = self.invariants[0].R @@ -525,7 +527,8 @@ def _findNullSpace(self): return def _findPosParameters(self): - """Find pparameters and their values for expressing `self.xyz`.""" + """Find pparameters and their values for expressing + `self.xyz`.""" usedsymbol = {} # parameter values depend on offset of self.xyz txyz = self.xyz @@ -542,8 +545,7 @@ def _findPosParameters(self): def _findUSpace(self): """Find independent U components with respect to invariant - rotations. - """ + rotations.""" n = len(self.invariants) R6zall = numpy.tile(-numpy.identity(6, dtype=float), (n, 1)) R6zall_iter = numpy.split(R6zall, n, axis=0) @@ -568,7 +570,8 @@ def _findUSpace(self): return def _findUParameters(self): - """Find Uparameters and their values for expressing `self.Uij`.""" + """Find Uparameters and their values for expressing + `self.Uij`.""" # permute indices as 00 11 22 01 02 12 10 20 21 diagorder = numpy.array((0, 4, 8, 1, 2, 5, 3, 6, 7)) Uijflat = self.Uij.flatten() @@ -583,7 +586,8 @@ def _findUParameters(self): return def _findeqUij(self): - """Adjust `self.Uij` and `self.eqUij` to be consistent with spacegroup.""" + """Adjust `self.Uij` and `self.eqUij` to be consistent with + spacegroup.""" self.Uij = numpy.zeros((3, 3), dtype=float) for i in range(len(self.Uparameters)): Usp = self.Uspace[i] @@ -598,7 +602,8 @@ def _findeqUij(self): return def positionFormula(self, pos, xyzsymbols=("x", "y", "z")): - """Formula of equivalent position with respect to generator site. + """Formula of equivalent position with respect to generator + site. Parameters ---------- @@ -646,7 +651,8 @@ def positionFormula(self, pos, xyzsymbols=("x", "y", "z")): return dict(zip(("x", "y", "z"), xyzformula)) def UFormula(self, pos, Usymbols=stdUsymbols): - """List of atom displacement formulas with custom parameter symbols. + """List of atom displacement formulas with custom parameter + symbols. Parameters ---------- @@ -902,7 +908,8 @@ def __init__(self, spacegroup, positions, Uijs=None, sgoffset=[0, 0, 0], eps=Non return def _findConstraints(self): - """Find constraints for positions and anisotropic displacements `Uij`.""" + """Find constraints for positions and anisotropic displacements + `Uij`.""" numpos = len(self.positions) # canonical xyzsymbols and Usymbols xyzsymbols = [smbl + str(i) for i in range(numpos) for smbl in "xyz"] @@ -994,7 +1001,8 @@ def translatesymbol(matchobj): return rv def positionFormulasPruned(self, xyzsymbols=None): - """List of position formula dictionaries with constant items removed. + """List of position formula dictionaries with constant items + removed. See also -------- @@ -1014,7 +1022,8 @@ def positionFormulasPruned(self, xyzsymbols=None): return rv def UparSymbols(self): - """Return list of standard atom displacement parameter symbols.""" + """Return list of standard atom displacement parameter + symbols.""" return [n for n, v in self.Upars] def UparValues(self): @@ -1022,7 +1031,8 @@ def UparValues(self): return [v for n, v in self.Upars] def UFormulas(self, Usymbols=None): - """List of atom displacement formulas with custom parameter symbols. + """List of atom displacement formulas with custom parameter + symbols. Parameters ---------- @@ -1059,8 +1069,8 @@ def translatesymbol(matchobj): return rv def UFormulasPruned(self, Usymbols=None): - """List of atom displacement formula dictionaries with constant items - removed. + """List of atom displacement formula dictionaries with constant + items removed. See Also -------- diff --git a/src/diffpy/structure/utils.py b/src/diffpy/structure/utils.py index e5fa3ce3..facab843 100644 --- a/src/diffpy/structure/utils.py +++ b/src/diffpy/structure/utils.py @@ -12,9 +12,7 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - -"""Small shared functions. -""" +"""Small shared functions.""" from collections.abc import Iterable as _Iterable @@ -38,7 +36,8 @@ def isfloat(s): def atomBareSymbol(smbl): - """Remove atom type string stripped of isotope and ion charge symbols. + """Remove atom type string stripped of isotope and ion charge + symbols. This function removes any blank, isotope numbers (0-9), leading hyphens (-), and ion charge symbols (1-9)(+-) from the given atom type string, returning only the bare element symbol. diff --git a/src/diffpy/structure/version.py b/src/diffpy/structure/version.py index be7f6a2d..605c9101 100644 --- a/src/diffpy/structure/version.py +++ b/src/diffpy/structure/version.py @@ -1,18 +1,17 @@ #!/usr/bin/env python ############################################################################## # -# (c) 2024 The Trustees of Columbia University in the City of New York. +# (c) 2024-2025 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: Chris Farrow, Pavol Juhas, Simon Billinge, Billinge Group members. # # See GitHub contributions for a more detailed list of contributors. -# https://github.com/diffpy/diffpy.structure/graphs/contributors +# https://github.com/diffpy/diffpy.structure/graphs/contributors # noqa: E501 # # See LICENSE.rst for license information. # ############################################################################## - """Definition of __version__.""" # We do not use the other three variables, but can be added back if needed. diff --git a/tests/test_atom.py b/tests/test_atom.py index 67009e80..6c7dd32d 100644 --- a/tests/test_atom.py +++ b/tests/test_atom.py @@ -12,10 +12,7 @@ # See LICENSE.txt for license information. # ############################################################################## - -""" -Unit tests for the Atom class. -""" +"""Unit tests for the Atom class.""" import unittest @@ -31,7 +28,7 @@ class TestAtom(unittest.TestCase): def test___init__(self): - """check Atom.__init__()""" + """Check Atom.__init__()""" a = Atom() self.assertEqual("", a.element) self.assertTrue((a.xyz == 0).all()) @@ -78,7 +75,7 @@ def test___init__(self): # return def test_xyz_cartn(self): - """check Atom.xyz_cartn property""" + """Check Atom.xyz_cartn property.""" hexagonal = Lattice(1, 1, 1, 90, 90, 120) a0 = Atom("C", [0, 0, 0], lattice=hexagonal) a1 = Atom("C", [1, 1, 1], lattice=hexagonal) diff --git a/tests/test_lattice.py b/tests/test_lattice.py index a2b22d38..e98ec95c 100644 --- a/tests/test_lattice.py +++ b/tests/test_lattice.py @@ -12,9 +12,7 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - -"""Unit tests for Lattice class. -""" +"""Unit tests for Lattice class.""" import unittest @@ -27,7 +25,7 @@ class TestLattice(unittest.TestCase): - """test methods of Lattice class""" + """Test methods of Lattice class.""" def setUp(self): self.lattice = Lattice() @@ -53,7 +51,7 @@ def test___init__(self): return def test_setLatPar(self): - """check calculation of standard unit cell vectors""" + """Check calculation of standard unit cell vectors.""" from math import cos, radians, sqrt from numpy import dot @@ -75,7 +73,7 @@ def cosd(x): return def test_latpar_properties(self): - """check assignment to a, b, c, alpha, beta, gamma.""" + """Check assignment to a, b, c, alpha, beta, gamma.""" lat = self.lattice lat.a = 2 lat.b = 4 @@ -136,7 +134,7 @@ def test_readonly_properties(self): return def test_setLatBase(self): - """check calculation of unit cell rotation""" + """Check calculation of unit cell rotation.""" base = numpy.array([[1.0, 1.0, 0.0], [0.0, 1.0, 1.0], [1.0, 0.0, 1.0]]) self.lattice.setLatBase(base) self.assertAlmostEqual(self.lattice.a, numpy.sqrt(2.0), self.places) @@ -161,7 +159,7 @@ def test_setLatBase(self): return def test_reciprocal(self): - """check calculation of reciprocal lattice.""" + """Check calculation of reciprocal lattice.""" r1 = self.lattice.reciprocal() self.assertEqual((1, 1, 1, 90, 90, 90), r1.abcABG()) L2 = Lattice(2, 4, 8, 90, 90, 90) @@ -172,7 +170,7 @@ def test_reciprocal(self): return def test_dot(self): - """check dot product of lattice vectors.""" + """Check dot product of lattice vectors.""" L = self.lattice L.setLatPar(gamma=120) self.assertAlmostEqual(-0.5, L.dot([1, 0, 0], [0, 1, 0]), self.places) @@ -184,7 +182,7 @@ def test_dot(self): return def test_norm(self): - """check norm of a lattice vector.""" + """Check norm of a lattice vector.""" self.assertEqual(1, self.lattice.norm([1, 0, 0])) u = numpy.array([[3, 4, 0], [1, 1, 1]]) self.assertTrue(numpy.allclose([5, 3**0.5], self.lattice.norm(u))) @@ -193,7 +191,7 @@ def test_norm(self): return def test_rnorm(self): - """check norm of a reciprocal vector.""" + """Check norm of a reciprocal vector.""" L = self.lattice L.setLatPar(1, 1.5, 2.3, 80, 95, 115) r = L.reciprocal() @@ -204,7 +202,7 @@ def test_rnorm(self): return def test_dist(self): - """check dist function for distance between lattice points.""" + """Check dist function for distance between lattice points.""" L = self.lattice L.setLatPar(1, 1.5, 2.3, 80, 95, 115) u = [0.1, 0.3, 0.7] @@ -220,7 +218,7 @@ def test_dist(self): return def test_angle(self): - """check angle calculation between lattice vectors.""" + """Check angle calculation between lattice vectors.""" from math import acos, degrees L = self.lattice @@ -240,7 +238,7 @@ def test_angle(self): return def test_repr(self): - """check string representation of this lattice""" + """Check string representation of this lattice.""" r = repr(self.lattice) self.assertEqual(r, "Lattice()") self.lattice.setLatPar(1, 2, 3, 10, 20, 30) diff --git a/tests/test_loadstructure.py b/tests/test_loadstructure.py index 4f099c7d..8bd1ec21 100644 --- a/tests/test_loadstructure.py +++ b/tests/test_loadstructure.py @@ -1,7 +1,6 @@ #!/usr/bin/env python -"""Unit tests for the loadStructure factory. -""" +"""Unit tests for the loadStructure factory.""" import unittest @@ -18,7 +17,7 @@ def prepare_fixture(self, datafile): self.datafile = datafile def test_xcfg(self): - """check loading of atomeye xcfg format""" + """Check loading of atomeye xcfg format.""" f = self.datafile("BubbleRaftShort.xcfg") stru = loadStructure(f) self.assertTrue(type(stru) is Structure) @@ -26,14 +25,14 @@ def test_xcfg(self): return def test_discus(self): - """check loading of discus file format""" + """Check loading of discus file format.""" f = self.datafile("Ni-discus.stru") stru = loadStructure(f) self.assertTrue(type(stru) is PDFFitStructure) return def test_cif(self): - """check loading of CIF file format""" + """Check loading of CIF file format.""" f = self.datafile("PbTe.cif") stru = loadStructure(f) self.assertTrue(isinstance(stru, Structure)) @@ -41,20 +40,22 @@ def test_cif(self): return def test_badfile(self): - """check loading of CIF file format""" + """Check loading of CIF file format.""" f = self.datafile("Ni-bad.stru") self.assertRaises(StructureFormatError, loadStructure, f) return def test_goodkwarg(self): - """check loading of CIF file and passing of parser keyword argument.""" + """Check loading of CIF file and passing of parser keyword + argument.""" f = self.datafile("graphite.cif") stru = loadStructure(f, eps=1e-10) self.assertEqual(8, len(stru)) return def test_badkwarg(self): - """check loading of xyz file format with invalid keyword argument""" + """Check loading of xyz file format with invalid keyword + argument.""" f = self.datafile("bucky.xyz") self.assertRaises(TypeError, loadStructure, f, eps=1e-10) return diff --git a/tests/test_oldimports.py b/tests/test_oldimports.py deleted file mode 100644 index 9c6ff11d..00000000 --- a/tests/test_oldimports.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# diffpy.structure Complex Modeling Initiative -# (c) 2017 Brookhaven Science Associates, -# Brookhaven National Laboratory. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -""" -Unit tests for imports of old camel-case names. -""" - - -import importlib -import sys -import unittest -import warnings - -import diffpy - -# ---------------------------------------------------------------------------- - - -class TestOldImports(unittest.TestCase): - - @classmethod - def setUpClass(cls): - "Uncache any already-imported old modules." - for modname in tuple(sys.modules): - if modname.startswith("diffpy.Structure"): - del sys.modules[modname] # pragma: no cover - return - - def test_00TopImport(self): - """check import of diffpy.Structure""" - with warnings.catch_warnings(): - warnings.simplefilter("ignore", category=DeprecationWarning) - import diffpy.Structure as m0 - self.assertIs(diffpy.structure, m0) - # second import should raise no warning - with warnings.catch_warnings(): - warnings.simplefilter("error") - import diffpy.Structure as m1 - self.assertIs(diffpy.structure, m1) - return - - def test_O1SubmoduleImport(self): - """check import of diffpy.Structure submodules.""" - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always", category=DeprecationWarning) - import diffpy.Structure.SymmetryUtilities as symutil - - self.assertIs(DeprecationWarning, w[0].category) - self.assertIs(diffpy.structure.symmetryutilities, symutil) - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always", category=DeprecationWarning) - import diffpy.Structure.Parsers.P_cif as pcif - - self.assertIs(DeprecationWarning, w[0].category) - self.assertIs(diffpy.structure.parsers.p_cif, pcif) - self.assertRaises(ImportError, importlib.import_module, "diffpy.Structure.SSpaceGroups") - return - - -# End of class TestOldImports - -# ---------------------------------------------------------------------------- - -if __name__ == "__main__": - unittest.main() diff --git a/tests/test_p_cif.py b/tests/test_p_cif.py index 62bb25db..5676120b 100644 --- a/tests/test_p_cif.py +++ b/tests/test_p_cif.py @@ -12,9 +12,7 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - -"""Unit tests for diffpy.structure.parsers.p_cif module -""" +"""Unit tests for diffpy.structure.parsers.p_cif module.""" import unittest @@ -38,14 +36,14 @@ def tearDown(self): return def test_leading_float(self): - """check leading_float()""" + """Check leading_float()""" self.assertEqual(0.37, leading_float("0.37(3)")) self.assertEqual(0.37, leading_float("0.37ab\ncd")) self.assertRaises(ValueError, leading_float, "q1") return def test_getSymOp(self): - """check getSymOp()""" + """Check getSymOp()""" from diffpy.structure.spacegroups import Rot_X_mY_Z, SymOp, Tr_0_12_12 op = getSymOp("x,1/2-y,1/2+z") @@ -85,7 +83,7 @@ def tearDown(self): return def test_parse(self): - """check P_cif.parse()""" + """Check P_cif.parse()""" with open(self.pbteciffile) as fp1: sgood = fp1.read() with open(self.badciffile) as fp2: @@ -101,7 +99,7 @@ def test_parse(self): return def test_parseLines(self): - """check P_cif.parseLines()""" + """Check P_cif.parseLines()""" with open(self.pbteciffile) as fp1: goodlines = fp1.readlines() with open(self.badciffile) as fp2: @@ -117,7 +115,7 @@ def test_parseLines(self): return def test_parseFile(self): - """check P_cif.parseFile()""" + """Check P_cif.parseFile()""" # pbteciffile stru = self.pfile.parseFile(self.pbteciffile) self.assertEqual(8, len(stru)) @@ -200,7 +198,7 @@ def test_parseFile(self): # return def test_write_and_read(self): - """high-level check of P_cif.tostring()""" + """High-level check of P_cif.tostring()""" # high-level check stru_check = Structure() stru_check.read(self.cdsebulkpdffitfile) @@ -370,7 +368,8 @@ def test_curly_brace(self): return def test_getParser(self): - """Test passing of eps keyword argument by getParser function.""" + """Test passing of eps keyword argument by getParser + function.""" pcif = getParser("cif", eps=1e-6) grph = pcif.parseFile(self.graphiteciffile) self.assertEqual(8, len(grph)) diff --git a/tests/test_p_discus.py b/tests/test_p_discus.py index 8959718e..71f0d695 100644 --- a/tests/test_p_discus.py +++ b/tests/test_p_discus.py @@ -12,9 +12,7 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - -"""Unit tests for diffpy.structure.parsers.p_discus module -""" +"""Unit tests for diffpy.structure.parsers.p_discus module.""" import re import unittest @@ -28,7 +26,7 @@ class TestP_discus(unittest.TestCase): - """test Parser for PDFFit file format""" + """Test Parser for PDFFit file format.""" @pytest.fixture(autouse=True) def prepare_fixture(self, datafile): @@ -40,7 +38,7 @@ def setUp(self): self.places = 8 def test_read_discus_Ni(self): - """check reading of Ni structure in discus format""" + """Check reading of Ni structure in discus format.""" stru = self.stru stru.read(self.datafile("Ni-discus.stru"), self.format) f_title = "structure Ni FCC" @@ -61,7 +59,7 @@ def test_read_discus_Ni(self): return def test_except_other_formats(self): - """check exceptions when reading files in other formats""" + """Check exceptions when reading files in other formats.""" badfiles = [ "LiCl-bad.cif", "PbTe.cif", @@ -85,7 +83,7 @@ def test_except_other_formats(self): return def test_ignored_lines(self): - """check skipping of ignored lines in the header""" + """Check skipping of ignored lines in the header.""" r1 = "ignored record 1\n" r2 = "ignored record 2\n" with open(self.datafile("Ni-discus.stru")) as fp: @@ -101,7 +99,7 @@ def test_ignored_lines(self): return def test_spdiameter_parsing(self): - """check parsing of spdiameter record from a file.""" + """Check parsing of spdiameter record from a file.""" stru = self.stru stru.read(self.datafile("Ni-discus.stru"), self.format) self.assertEqual(0, stru.pdffit["spdiameter"]) @@ -122,7 +120,7 @@ def test_spdiameter_parsing(self): return def test_stepcut_parsing(self): - """check parsing of stepcut record from a file.""" + """Check parsing of stepcut record from a file.""" stru = self.stru stru.read(self.datafile("Ni-discus.stru"), self.format) self.assertEqual(0, stru.pdffit["stepcut"]) diff --git a/tests/test_p_pdffit.py b/tests/test_p_pdffit.py index f993cb4b..316f8ba2 100644 --- a/tests/test_p_pdffit.py +++ b/tests/test_p_pdffit.py @@ -12,9 +12,7 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - -"""Unit tests for diffpy.structure.parsers.p_pdffit module -""" +"""Unit tests for diffpy.structure.parsers.p_pdffit module.""" import re import unittest @@ -29,7 +27,7 @@ class TestP_pdffit(unittest.TestCase): - """test Parser for PDFFit file format""" + """Test Parser for PDFFit file format.""" @pytest.fixture(autouse=True) def prepare_fixture(self, datafile): @@ -41,7 +39,7 @@ def setUp(self): self.places = 8 def test_read_pdffit_ZnSb(self): - """check reading of ZnSb pdffit structure file""" + """Check reading of ZnSb pdffit structure file.""" stru = self.stru stru.read(self.datafile("ZnSb_RT_Q28X_VM_20_fxiso.rstr"), self.format) f_title = "Cell structure file of Zn4Sb3 #167 interstitial" @@ -86,7 +84,7 @@ def test_read_pdffit_ZnSb(self): self.assertAlmostEqual(s_sigo, f_sigo) def test_read_pdffit_Ni(self): - """check reading of Ni pdffit structure file""" + """Check reading of Ni pdffit structure file.""" stru = self.stru stru.read(self.datafile("Ni.stru"), self.format) f_title = "structure Ni FCC" @@ -119,7 +117,7 @@ def test_read_pdffit_Ni(self): self.assertAlmostEqual(s_o, f_o) def test_read_pdffit_Ni_prim123(self): - """check reading of Ni_prim supercell 1x2x3""" + """Check reading of Ni_prim supercell 1x2x3.""" stru = self.stru stru.read(self.datafile("Ni_prim123.stru"), self.format) s_lat = [ @@ -150,14 +148,14 @@ def test_read_pdffit_Ni_prim123(self): return def test_read_pdffit_bad(self): - """check exceptions when reading invalid pdffit file""" + """Check exceptions when reading invalid pdffit file.""" stru = self.stru self.assertRaises(StructureFormatError, stru.read, self.datafile("Ni-bad.stru"), self.format) self.assertRaises(StructureFormatError, stru.read, self.datafile("bucky.xyz"), self.format) return def test_writeStr_pdffit(self): - """check writing of normal xyz file""" + """Check writing of normal xyz file.""" stru = self.stru stru.read(self.datafile("Ni.stru"), self.format) with open(self.datafile("Ni.stru")) as fp: @@ -170,7 +168,7 @@ def test_writeStr_pdffit(self): return def test_huge_occupancy(self): - """check structure with huge occupancy can be read.""" + """Check structure with huge occupancy can be read.""" self.stru.read(self.datafile("Ni.stru"), self.format) self.stru[0].occupancy = 16e16 s_s = self.stru.writeStr(self.format) @@ -180,7 +178,7 @@ def test_huge_occupancy(self): return def test_ignored_lines(self): - """check skipping of ignored lines in the header""" + """Check skipping of ignored lines in the header.""" r1 = "ignored record 1" r2 = "ignored record 2" with open(self.datafile("Ni.stru")) as fp: @@ -196,7 +194,7 @@ def test_ignored_lines(self): return def test_spdiameter_parsing(self): - """check parsing of spdiameter record from a file.""" + """Check parsing of spdiameter record from a file.""" stru = self.stru stru.read(self.datafile("Ni.stru"), self.format) self.assertEqual(0, stru.pdffit["spdiameter"]) @@ -217,7 +215,7 @@ def test_spdiameter_parsing(self): return def test_stepcut_parsing(self): - """check parsing of stepcut record from a file.""" + """Check parsing of stepcut record from a file.""" stru = self.stru stru.read(self.datafile("Ni.stru"), self.format) self.assertEqual(0, stru.pdffit["stepcut"]) diff --git a/tests/test_parsers.py b/tests/test_parsers.py index a3f7f3c1..552154f0 100644 --- a/tests/test_parsers.py +++ b/tests/test_parsers.py @@ -12,9 +12,7 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - -"""Unit tests for structure.parsers module. -""" +"""Unit tests for structure.parsers module.""" import os import re @@ -31,7 +29,7 @@ class TestP_xyz(unittest.TestCase): - """test Parser for xyz file format""" + """Test Parser for xyz file format.""" @pytest.fixture(autouse=True) def prepare_fixture(self, datafile): @@ -54,7 +52,7 @@ def mktmpfile(self): return self.tmpnames[-1] def test_read_xyz(self): - """check reading of normal xyz file""" + """Check reading of normal xyz file.""" stru = self.stru stru.read(self.datafile("bucky.xyz"), self.format) s_els = [a.element for a in stru] @@ -63,7 +61,7 @@ def test_read_xyz(self): return def test_read_xyz_bad(self): - """check exceptions when reading invalid xyz file""" + """Check exceptions when reading invalid xyz file.""" stru = self.stru self.assertRaises(StructureFormatError, stru.read, self.datafile("bucky-bad1.xyz"), self.format) self.assertRaises(StructureFormatError, stru.read, self.datafile("bucky-bad2.xyz"), self.format) @@ -72,7 +70,7 @@ def test_read_xyz_bad(self): return def test_writeStr_xyz(self): - """check string representation of normal xyz file""" + """Check string representation of normal xyz file.""" stru = self.stru stru.title = "test of writeStr" stru.lattice = Lattice(1.0, 2.0, 3.0, 90.0, 90.0, 90.0) @@ -84,7 +82,7 @@ def test_writeStr_xyz(self): return def test_write_xyz(self): - """check writing of normal xyz file""" + """Check writing of normal xyz file.""" stru = self.stru stru.title = "test of writeStr" stru.lattice = Lattice(1.0, 2.0, 3.0, 90.0, 90.0, 90.0) @@ -105,7 +103,7 @@ def test_write_xyz(self): class TestP_rawxyz(unittest.TestCase): - """test Parser for rawxyz file format""" + """Test Parser for rawxyz file format.""" @pytest.fixture(autouse=True) def prepare_fixture(self, datafile): @@ -117,7 +115,7 @@ def setUp(self): return def test_read_plainxyz(self): - """check reading of a plain xyz file""" + """Check reading of a plain xyz file.""" stru = self.stru stru.read(self.datafile("bucky-plain.xyz"), self.format) s_els = [a.element for a in stru] @@ -126,13 +124,13 @@ def test_read_plainxyz(self): return def test_read_plainxyz_bad(self): - """check exceptions when reading invalid plain xyz file""" + """Check exceptions when reading invalid plain xyz file.""" stru = self.stru self.assertRaises(StructureFormatError, stru.read, self.datafile("bucky-plain-bad.xyz"), self.format) return def test_read_rawxyz(self): - """check reading of raw xyz file""" + """Check reading of raw xyz file.""" stru = self.stru stru.read(self.datafile("bucky-raw.xyz"), self.format) s_els = [a.element for a in stru] @@ -144,14 +142,14 @@ def test_read_rawxyz(self): return def test_read_rawxyz_bad(self): - """check exceptions when reading unsupported xy file""" + """Check exceptions when reading unsupported xy file.""" stru = self.stru self.assertRaises(StructureFormatError, stru.read, self.datafile("hexagon-raw-bad.xyz"), self.format) self.assertRaises(StructureFormatError, stru.read, self.datafile("hexagon-raw.xy"), self.format) return def test_writeStr_rawxyz(self): - """check writing of normal xyz file""" + """Check writing of normal xyz file.""" stru = self.stru stru.title = "test of writeStr" stru.lattice = Lattice(1.0, 2.0, 3.0, 90.0, 90.0, 90.0) @@ -174,7 +172,7 @@ def test_writeStr_rawxyz(self): class TestP_pdb(unittest.TestCase): - """test Parser for PDB file format""" + """Test Parser for PDB file format.""" @pytest.fixture(autouse=True) def prepare_fixture(self, datafile): @@ -186,7 +184,7 @@ def setUp(self): self.places = 3 def test_read_pdb_arginine(self): - """check reading of arginine PDB file""" + """Check reading of arginine PDB file.""" stru = self.stru stru.read(self.datafile("arginine.pdb"), self.format) f_els = [ @@ -234,7 +232,7 @@ def test_read_pdb_arginine(self): self.assertTrue(numpy.allclose(a0.xyz, [0.735, 2.219, 1.389])) def test_rwStr_pdb_CdSe(self): - """check conversion to PDB file format""" + """Check conversion to PDB file format.""" stru = self.stru stru.read(self.datafile("CdSe_bulk.stru"), "pdffit") s = stru.writeStr(self.format) @@ -275,7 +273,7 @@ def test_rwStr_pdb_CdSe(self): class TestP_xcfg(unittest.TestCase): - """test Parser for XCFG file format""" + """Test Parser for XCFG file format.""" @pytest.fixture(autouse=True) def prepare_fixture(self, datafile): @@ -287,7 +285,7 @@ def setUp(self): self.places = 6 def test_read_xcfg(self): - """check reading of BubbleRaft XCFG file""" + """Check reading of BubbleRaft XCFG file.""" stru = self.stru stru.read(self.datafile("BubbleRaftShort.xcfg"), self.format) f_els = 500 * ["Ar"] @@ -307,7 +305,7 @@ def test_read_xcfg(self): return def test_rwStr_xcfg_CdSe(self): - """check conversion to XCFG file format""" + """Check conversion to XCFG file format.""" stru = self.stru stru.read(self.datafile("CdSe_bulk.stru"), "pdffit") s = stru.writeStr(self.format) diff --git a/tests/test_spacegroups.py b/tests/test_spacegroups.py index c9980e17..bfd71382 100644 --- a/tests/test_spacegroups.py +++ b/tests/test_spacegroups.py @@ -12,9 +12,7 @@ # See LICENSE.txt for license information. # ############################################################################## - -"""Unit tests for diffpy.structure.spacegroups -""" +"""Unit tests for diffpy.structure.spacegroups.""" import unittest diff --git a/tests/test_structure.py b/tests/test_structure.py index 9c1a6308..65e851c1 100644 --- a/tests/test_structure.py +++ b/tests/test_structure.py @@ -12,9 +12,7 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - -"""Unit tests for Structure class. -""" +"""Unit tests for Structure class.""" import copy @@ -30,7 +28,7 @@ class TestStructure(unittest.TestCase): - """test methods of Structure class""" + """Test methods of Structure class.""" @pytest.fixture(autouse=True) def prepare_fixture(self, datafile): @@ -57,7 +55,7 @@ def setUp(self): return def test___init__(self): - """check Structure.__init__()""" + """Check Structure.__init__()""" atoms = [Atom("C", [0, 0, 0]), Atom("C", [0.5, 0.5, 0.5])] self.assertRaises(ValueError, Structure, atoms, filename=self.teifile) self.assertRaises(ValueError, Structure, lattice=Lattice(), filename=self.teifile) @@ -73,7 +71,7 @@ def test___init__(self): return def test_copy(self): - """check Structure.copy()""" + """Check Structure.copy()""" class MyDerivedStructure(Structure): def __copy__(self): @@ -97,7 +95,7 @@ def __copy__(self): return def test___copy__(self): - """check Structure.__copy__()""" + """Check Structure.__copy__()""" cdse = Structure(filename=self.cdsefile) cdse_str = cdse.writeStr("pdffit") cdse2 = copy.copy(cdse) @@ -120,7 +118,7 @@ def test___copy__(self): # return def test_assignUniqueLabels(self): - """check Structure.assignUniqueLabels()""" + """Check Structure.assignUniqueLabels()""" self.assertEqual("", "".join([a.label for a in self.stru])) self.stru.assignUniqueLabels() self.assertEqual("C1", self.stru[0].label) @@ -128,7 +126,7 @@ def test_assignUniqueLabels(self): return def test_distance(self): - """check Structure.distance()""" + """Check Structure.distance()""" from math import sqrt self.stru.assignUniqueLabels() @@ -140,7 +138,7 @@ def test_distance(self): return def test_angle(self): - """check Structure.angle()""" + """Check Structure.angle()""" cdse = Structure(filename=self.cdsefile) cdse.assignUniqueLabels() self.assertEqual(109, round(cdse.angle(0, 2, 1))) @@ -148,7 +146,8 @@ def test_angle(self): return def test_placeInLattice(self): - """check Structure.placeInLattice() -- conversion of coordinates""" + """Check Structure.placeInLattice() -- conversion of + coordinates.""" stru = self.stru new_lattice = Lattice(0.5, 0.5, 0.5, 90, 90, 60) stru.placeInLattice(new_lattice) @@ -174,14 +173,14 @@ def test_placeInLattice(self): # return def test_aslist(self): - """check Structure.tolist()""" + """Check Structure.tolist()""" lst = self.stru.tolist() self.assertEqual(tuple(lst), tuple(self.stru)) self.assertEqual(list, type(lst)) return def test_append(self): - """check Structure.append()""" + """Check Structure.append()""" a = Atom("Si", (0.1, 0.2, 0.3)) lat = self.stru.lattice self.stru.append(a) @@ -195,7 +194,7 @@ def test_append(self): return def test_insert(self): - """check Structure.insert()""" + """Check Structure.insert()""" a = Atom("Si", (0.1, 0.2, 0.3)) lat = self.stru.lattice self.stru.insert(1, a) @@ -209,7 +208,7 @@ def test_insert(self): return def test_extend(self): - """check Structure.extend()""" + """Check Structure.extend()""" stru = self.stru cdse = Structure(filename=self.cdsefile) lst = stru.tolist() @@ -221,7 +220,7 @@ def test_extend(self): return def test___getitem__(self): - """check Structure.__getitem__()""" + """Check Structure.__getitem__()""" stru = self.stru self.assertTrue(stru[0] is stru.tolist()[0]) intidx = list(range(len(stru)))[::-1] @@ -248,14 +247,14 @@ def test___getitem__(self): return def test___getitem__slice(self): - """check Structure.__getitem__() with a slice argument""" + """Check Structure.__getitem__() with a slice argument.""" stru = self.stru self.assertEqual([stru[0]], stru[:1].tolist()) self.assertEqual([stru[1], stru[0]], stru[::-1].tolist()) return def test___setitem__(self): - """check Structure.__setitem__()""" + """Check Structure.__setitem__()""" a = Atom("Si", (0.1, 0.2, 0.3)) lat = self.stru.lattice self.stru[1] = a @@ -269,7 +268,7 @@ def test___setitem__(self): return def test___setitem__slice(self): - """check Structure.__setitem__() with a slice argument""" + """Check Structure.__setitem__() with a slice argument.""" a = Atom("Si", (0.1, 0.2, 0.3)) lat = self.stru.lattice self.stru[:] = [a] @@ -283,7 +282,7 @@ def test___setitem__slice(self): return def test___add__(self): - """check Structure.__add__()""" + """Check Structure.__add__()""" stru = self.stru cdse = Structure(filename=self.cdsefile) total = stru + cdse @@ -299,7 +298,7 @@ def test___add__(self): return def test___iadd__(self): - """check Structure.__iadd__()""" + """Check Structure.__iadd__()""" stru = self.stru lat0 = stru.lattice lst = stru.tolist() @@ -316,7 +315,7 @@ def test___iadd__(self): return def test___sub__(self): - """check Structure.__sub__()""" + """Check Structure.__sub__()""" cdse = Structure(filename=self.cdsefile) cadmiums = cdse - cdse[2:] self.assertEqual(2, len(cadmiums)) @@ -329,7 +328,7 @@ def test___sub__(self): return def test___isub__(self): - """check Structure.__isub__()""" + """Check Structure.__isub__()""" cdse = Structure(filename=self.cdsefile) lat = cdse.lattice lst = cdse.tolist() @@ -343,7 +342,7 @@ def test___isub__(self): return def test___mul__(self): - """check Structure.__mul__()""" + """Check Structure.__mul__()""" cdse = Structure(filename=self.cdsefile) self.assertEqual(12, len(set(3 * cdse))) self.assertEqual(12, len(set(cdse * 3))) @@ -356,7 +355,7 @@ def test___mul__(self): return def test___imul__(self): - """check Structure.__imul__()""" + """Check Structure.__imul__()""" cdse = Structure(filename=self.cdsefile) lat = cdse.lattice els = cdse.element @@ -374,7 +373,7 @@ def test___imul__(self): return def test__get_lattice(self): - """check Structure._get_lattice()""" + """Check Structure._get_lattice()""" lat = Lattice() stru = Structure() self.assertEqual((1, 1, 1, 90, 90, 90), stru.lattice.abcABG()) @@ -383,14 +382,14 @@ def test__get_lattice(self): return def test__set_lattice(self): - """check Structure._set_lattice()""" + """Check Structure._set_lattice()""" lat = Lattice() self.stru.lattice = lat self.assertEqual(2 * [lat], [a.lattice for a in self.stru]) return def test_composition(self): - """check Structure.composition property""" + """Check Structure.composition property.""" stru = self.stru self.assertEqual({"C": 2}, stru.composition) stru *= 2 @@ -400,7 +399,7 @@ def test_composition(self): return def test_element(self): - """check Structure.element""" + """Check Structure.element.""" stru = self.stru cdse = self.cdse self.assertEqual("Cd Cd Se Se".split(), cdse.element.tolist()) @@ -410,7 +409,7 @@ def test_element(self): return def test_xyz(self): - """check Structure.xyz""" + """Check Structure.xyz.""" stru = self.stru self.assertEqual((2, 3), stru.xyz.shape) self.assertTrue(numpy.array_equal([1, 1, 1], stru.xyz[1])) @@ -428,7 +427,7 @@ def test_xyz(self): return def test_x(self): - """check Structure.x""" + """Check Structure.x.""" cdse = self.cdse self.assertEqual((4,), cdse.x.shape) self.assertAlmostEqual(0.6666, cdse.x[3], 5) @@ -439,7 +438,7 @@ def test_x(self): return def test_y(self): - """check Structure.y""" + """Check Structure.y.""" cdse = self.cdse self.assertEqual((4,), cdse.y.shape) self.assertAlmostEqual(0.3333, cdse.y[3], 5) @@ -450,7 +449,7 @@ def test_y(self): return def test_z(self): - """check Structure.z""" + """Check Structure.z.""" cdse = self.cdse self.assertEqual((4,), cdse.z.shape) self.assertAlmostEqual(0.87667, cdse.z[3], 5) @@ -461,7 +460,7 @@ def test_z(self): return def test_label(self): - """check Structure.label""" + """Check Structure.label.""" cdse = Structure(filename=self.cdsefile) self.assertEqual(4 * [""], cdse.label.tolist()) cdse.assignUniqueLabels() @@ -471,7 +470,7 @@ def test_label(self): return def test_occupancy(self): - """check Structure.occupancy""" + """Check Structure.occupancy.""" cdse = self.cdse self.assertTrue(numpy.array_equal(numpy.ones(4), cdse.occupancy)) self.stru.occupancy *= 0.5 @@ -481,7 +480,7 @@ def test_occupancy(self): return def test_xyz_cartn(self): - """check Structure.xyz_cartn""" + """Check Structure.xyz_cartn.""" pbte = copy.copy(self.pbte) self.assertEqual((8, 3), pbte.xyz_cartn.shape) self.assertTrue(numpy.allclose(6.461 / 2.0 * numpy.ones(3), pbte.xyz_cartn[0])) @@ -491,7 +490,7 @@ def test_xyz_cartn(self): return def test_anisotropy(self): - """check Structure.anisotropy""" + """Check Structure.anisotropy.""" self.assertEqual((2,), self.stru.anisotropy.shape) self.assertFalse(numpy.any(self.stru.anisotropy)) tei = copy.copy(self.tei) @@ -508,7 +507,7 @@ def test_anisotropy(self): return def test_U(self): - """check Structure.U""" + """Check Structure.U.""" stru = self.stru self.assertEqual((2, 3, 3), stru.U.shape) self.assertFalse(numpy.any(stru.anisotropy)) @@ -530,7 +529,7 @@ def test_U(self): return def test_Uisoequiv(self): - """check Structure.Uisoequiv""" + """Check Structure.Uisoequiv.""" tei = copy.copy(self.tei) self.assertEqual((16,), tei.Uisoequiv.shape) self.assertAlmostEqual(0.019227, tei.Uisoequiv[0], 6) @@ -543,7 +542,7 @@ def test_Uisoequiv(self): return def test_Uij(self): - """check Structure.Uij""" + """Check Structure.Uij.""" stru = self.stru stru[1].anisotropy = True stru[1].U = [[1.1, 0.12, 0.13], [0.12, 2.2, 0.23], [0.13, 0.23, 3.3]] @@ -558,7 +557,7 @@ def test_Uij(self): return def test_Bisoequiv(self): - """check Structure.Bisoequiv""" + """Check Structure.Bisoequiv.""" utob = 8 * numpy.pi**2 tei = copy.copy(self.tei) self.assertEqual((16,), tei.Bisoequiv.shape) @@ -572,7 +571,7 @@ def test_Bisoequiv(self): return def test_Bij(self): - """check Structure.Bij""" + """Check Structure.Bij.""" stru = self.stru stru[1].anisotropy = True stru[1].U = [[1.1, 0.12, 0.13], [0.12, 2.2, 0.23], [0.13, 0.23, 3.3]] diff --git a/tests/test_supercell.py b/tests/test_supercell.py index 0e840dfa..d20434ca 100644 --- a/tests/test_supercell.py +++ b/tests/test_supercell.py @@ -12,9 +12,7 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - -"""Unit tests for supercell.py -""" +"""Unit tests for supercell.py.""" import unittest @@ -51,14 +49,14 @@ def tearDown(self): return def test_exceptions(self): - """check argument checking of supercell.""" + """Check argument checking of supercell.""" self.assertRaises(ValueError, supercell, self.stru_ni, (0, 1, 1)) self.assertRaises(ValueError, supercell, self.stru_ni, (0, 1)) self.assertRaises(TypeError, supercell, list(self.stru_ni), (1, 1, 1)) return def test_ni_supercell(self): - """check supercell expansion for Ni.""" + """Check supercell expansion for Ni.""" ni_123 = supercell(self.stru_ni, (1, 2, 3)) self.assertEqual(6 * len(self.stru_ni), len(ni_123)) a, b, c = self.stru_ni.lattice.abcABG()[:3] @@ -74,7 +72,7 @@ def test_ni_supercell(self): return def test_cdse_supercell(self): - """check supercell expansion for CdSe.""" + """Check supercell expansion for CdSe.""" cdse_222 = supercell(self.stru_cdse, (2, 2, 2)) # new atoms should be grouped together elems = sum([8 * [a.element] for a in self.stru_cdse], []) diff --git a/tests/test_symmetryutilities.py b/tests/test_symmetryutilities.py index c4de983b..5e733906 100644 --- a/tests/test_symmetryutilities.py +++ b/tests/test_symmetryutilities.py @@ -12,9 +12,7 @@ # See LICENSE_DANSE.txt for license information. # ############################################################################## - -"""Unit tests for SymmetryUtilities.py -""" +"""Unit tests for SymmetryUtilities.py.""" import re import sys @@ -46,7 +44,7 @@ def tearDown(self): return def test_isSpaceGroupLatPar(self): - """check isSpaceGroupLatPar()""" + """Check isSpaceGroupLatPar()""" triclinic = GetSpaceGroup("P1") monoclinic = GetSpaceGroup("P2") orthorhombic = GetSpaceGroup("P222") @@ -70,13 +68,13 @@ def test_isSpaceGroupLatPar(self): return def test_sgtbx_spacegroup_aliases(self): - """check GetSpaceGroup for non-standard aliases from sgtbx.""" + """Check GetSpaceGroup for non-standard aliases from sgtbx.""" self.assertIs(GetSpaceGroup("Fm3m"), GetSpaceGroup(225)) self.assertIs(GetSpaceGroup("Ia3d"), GetSpaceGroup("I a -3 d")) return def test_expandPosition(self): - """check expandPosition()""" + """Check expandPosition()""" # ok again Ni example fcc = GetSpaceGroup(225) pos, pops, pmult = expandPosition(fcc, [0, 0, 0]) @@ -87,14 +85,14 @@ def test_expandPosition(self): return def test_pruneFormulaDictionary(self): - """check pruneFormulaDictionary()""" + """Check pruneFormulaDictionary()""" fmdict = {"x": "3*y-0.17", "y": "0", "z": "0.13"} pruned = pruneFormulaDictionary(fmdict) self.assertEqual({"x": "3*y-0.17"}, pruned) return def test_isconstantFormula(self): - """check isconstantFormula()""" + """Check isconstantFormula()""" self.assertFalse(isconstantFormula("x-y+z")) self.assertTrue(isconstantFormula("6.023e23")) self.assertTrue(isconstantFormula("22/7")) @@ -120,14 +118,14 @@ def tearDown(self): return def test___init__(self): - """check _Position2Tuple.__init__()""" + """Check _Position2Tuple.__init__()""" self.assertNotEqual(0.0, self.pos2tuple.eps) self.pos2tuple = _Position2Tuple(1.0 / sys.maxsize / 2) self.assertEqual(0.0, self.pos2tuple.eps) return def test___call__(self): - """check _Position2Tuple.__call__()""" + """Check _Position2Tuple.__call__()""" pos2tuple = self.pos2tuple positions = numpy.zeros((100, 3), dtype=float) positions[:, 0] = numpy.arange(100) / 100.0 * pos2tuple.eps + 0.1 @@ -203,7 +201,7 @@ def tearDown(self): return def test___init__(self): - """check GeneratorSite.__init__()""" + """Check GeneratorSite.__init__()""" # check multiplicities self.assertEqual(2, self.g117c.multiplicity) self.assertEqual(4, self.g117h.multiplicity) @@ -231,7 +229,7 @@ def test_signedRatStr(self): return def test_positionFormula(self): - """check GeneratorSite.positionFormula()""" + """Check GeneratorSite.positionFormula()""" # 117c self.assertEqual([], self.g117c.pparameters) self.assertEqual([("x", self.x)], self.g117h.pparameters) @@ -266,7 +264,7 @@ def test_positionFormula_sg209(self): return def test_UFormula(self): - """check GeneratorSite.UFormula()""" + """Check GeneratorSite.UFormula()""" # Ref: Willis and Pryor, Thermal Vibrations in Crystallography, # Cambridge University Press 1975, p. 104-110 smbl = ("A", "B", "C", "D", "E", "F") @@ -316,7 +314,8 @@ def test_UFormula(self): return def test_UFormula_g186c_eqxyz(self): - """Check rotated U formulas at the symmetry positions of c-site in 186.""" + """Check rotated U formulas at the symmetry positions of c-site + in 186.""" sg186 = GetSpaceGroup(186) crules = [ {"U11": "A", "U22": "A", "U33": "C", "U12": "D", "U13": "E", "U23": "-E"}, @@ -355,7 +354,7 @@ def test_UFormula_self_reference(self): return def test__findUParameters(self): - """check GeneratorSite._findUParameters()""" + """Check GeneratorSite._findUParameters()""" # by default all Uparameters equal zero, this would fail for NaNs for gen in TestGeneratorSite.generators.values(): for usym, uval in gen.Uparameters: @@ -372,7 +371,7 @@ def test__findUParameters(self): return def test_eqIndex(self): - """check GeneratorSite.eqIndex()""" + """Check GeneratorSite.eqIndex()""" self.assertEqual(13, self.g227oc.eqIndex(self.g227oc.eqxyz[13])) return @@ -391,7 +390,7 @@ def tearDown(self): return def test___init__(self): - """check SymmetryConstraints.__init__()""" + """Check SymmetryConstraints.__init__()""" sg225 = GetSpaceGroup(225) # initialize from nested lists and arrays from ExpandAsymmetricUnit eau = ExpandAsymmetricUnit(sg225, [[0, 0, 0]]) @@ -431,7 +430,7 @@ def test_corepos(self): return def test_Uisotropy(self): - """check isotropy value for ADP-s at specified sites.""" + """Check isotropy value for ADP-s at specified sites.""" sg225 = GetSpaceGroup(225) corepos = [[0, 0, 0], [0.1, 0.13, 0.17]] eau = ExpandAsymmetricUnit(sg225, corepos) @@ -466,7 +465,7 @@ def test_Uisotropy(self): # return # def test_UparSymbols(self): - """check SymmetryConstraints.UparSymbols()""" + """Check SymmetryConstraints.UparSymbols()""" sg1 = GetSpaceGroup(1) sg225 = GetSpaceGroup(225) pos = [[0, 0, 0]] @@ -478,7 +477,7 @@ def test_UparSymbols(self): return def test_UparValues(self): - """check SymmetryConstraints.UparValues()""" + """Check SymmetryConstraints.UparValues()""" places = 12 sg1 = GetSpaceGroup(1) sg225 = GetSpaceGroup(225) diff --git a/tests/test_version.py b/tests/test_version.py index e62433e1..5d55a864 100644 --- a/tests/test_version.py +++ b/tests/test_version.py @@ -1,10 +1,10 @@ -"""Unit tests for __version__.py -""" +"""Unit tests for __version__.py.""" -import diffpy.structure +import diffpy.structure # noqa def test_package_version(): - """Ensure the package version is defined and not set to the initial placeholder.""" + """Ensure the package version is defined and not set to the initial + placeholder.""" assert hasattr(diffpy.structure, "__version__") assert diffpy.structure.__version__ != "0.0.0"