From 7963db69d5c90a58f4a2189a47eef14a9a3398cc Mon Sep 17 00:00:00 2001 From: Zhi Ming Xu Date: Wed, 25 Mar 2026 22:35:21 -0400 Subject: [PATCH 1/4] skpkg: use package update to run skpkg on files --- .github/ISSUE_TEMPLATE/release_checklist.md | 10 +-- .../build-and-publish-docs-on-dispatch.yml | 18 ++++++ .../workflows/build-wheel-release-upload.yml | 64 ++++++++++++++++++- .github/workflows/check-news-item.yml | 2 +- .github/workflows/matrix-and-codecov.yml | 21 ++++++ AUTHORS.rst | 2 +- CODE-OF-CONDUCT.rst | 2 +- LICENSE.rst | 2 +- README.rst | 2 +- cookiecutter.json | 12 ++-- docs/source/api/diffpy.pdffit2.rst | 24 +++++++ docs/source/conf.py | 6 +- docs/source/index.rst | 8 ++- pyproject.toml | 17 +++-- src/diffpy/__init__.py | 2 +- src/diffpy/pdffit2/__init__.py | 4 +- src/diffpy/pdffit2/version.py | 2 +- 17 files changed, 165 insertions(+), 33 deletions(-) create mode 100644 .github/workflows/build-and-publish-docs-on-dispatch.yml create mode 100644 .github/workflows/matrix-and-codecov.yml diff --git a/.github/ISSUE_TEMPLATE/release_checklist.md b/.github/ISSUE_TEMPLATE/release_checklist.md index c382844..9b287ca 100644 --- a/.github/ISSUE_TEMPLATE/release_checklist.md +++ b/.github/ISSUE_TEMPLATE/release_checklist.md @@ -1,9 +1,11 @@ ---- + --- + 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: @@ -11,13 +13,13 @@ assignees: "" - [ ] 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. -- [ ] The `FALLBACK_VERSION` in `setup.py` has been updated to the latest version on PyPI. -- [ ] 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. +- [ ] Locally rendered documentation contains all appropriate pages, tutorials, and other human-written text is up-to-date with any changes in the code. +- [ ] All API references are included. To check this, run `conda install scikit-package` and then `package build api-doc`. Review any edits made by rerendering the docs locally. - [ ] 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. +- [ ] Dispatch matrix testing to test the release on all Python versions and systems. If you do not have permission to run this workflow, tag the maintainer and say `@maintainer, please dispatch matrix testing workflow`. 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: diff --git a/.github/workflows/build-and-publish-docs-on-dispatch.yml b/.github/workflows/build-and-publish-docs-on-dispatch.yml new file mode 100644 index 0000000..406f551 --- /dev/null +++ b/.github/workflows/build-and-publish-docs-on-dispatch.yml @@ -0,0 +1,18 @@ +name: Build and Publish Docs on Dispatch + +on: + workflow_dispatch: + +jobs: + get-python-version: + uses: scikit-package/release-scripts/.github/workflows/_get-python-version-latest.yml@v0 + with: + python_version: 0 + + docs: + uses: scikit-package/release-scripts/.github/workflows/_release-docs.yml@v0 + with: + project: diffpy.pdffit2 + c_extension: true + headless: false + python_version: ${{ fromJSON(needs.get-python-version.outputs.latest_python_version) }} diff --git a/.github/workflows/build-wheel-release-upload.yml b/.github/workflows/build-wheel-release-upload.yml index 5dec5f6..2835880 100644 --- a/.github/workflows/build-wheel-release-upload.yml +++ b/.github/workflows/build-wheel-release-upload.yml @@ -1,18 +1,76 @@ -name: Release (GitHub/PyPI) and Deploy Docs +name: Build Wheel and Release +# Trigger on tag push or manual dispatch. +# Tag and release privilege are verified inside the reusable workflow. on: workflow_dispatch: push: tags: - - "*" # Trigger on all tags initially, but tag and release privilege are verified in _build-wheel-release-upload.yml + - "*" + +# ── Release modality ────────────────────────────────────────────────────────── +# Three options are provided below. Only ONE job should be active at a time. +# To switch: comment out the active job and uncomment your preferred option, +# then commit the change to main before tagging a release. +# ───────────────────────────────────────────────────────────────────────────── jobs: + # Option 1 (default): Release to GitHub, publish to PyPI, and deploy docs. + # + # The wheel is uploaded to PyPI so users can install with `pip install`. + # A GitHub release is created with the changelog as the release body, and + # the Sphinx documentation is rebuilt and deployed to GitHub Pages. + # + # Choose this for open-source packages distributed via PyPI and/or + # conda-forge where broad public availability is the goal. build-release: uses: scikit-package/release-scripts/.github/workflows/_build-wheel-release-upload.yml@v0 with: project: diffpy.pdffit2 c_extension: true - maintainer_GITHUB_username: sbillinge + maintainer_github_username: sbillinge secrets: PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} PAT_TOKEN: ${{ secrets.PAT_TOKEN }} + + # Option 2: Release to GitHub and deploy docs, without publishing to PyPI. + # + # A GitHub release is created and the Sphinx docs are deployed, but the + # wheel is not uploaded to PyPI. The source code remains publicly visible + # on GitHub and can be installed directly from there. + # + # Choose this when the package is public but you prefer to keep it off the + # default pip index — for example, if you distribute via conda-forge only, + # or if the package is not yet ready for a permanent PyPI presence. + # + # To use: comment out Option 1 above and uncomment the lines below. + # build-release-no-pypi: + # uses: scikit-package/release-scripts/.github/workflows/_build-release-github-no-pypi.yml@v0 + # with: + # project: diffpy.pdffit2 + # c_extension: true + # maintainer_github_username: sbillinge + # secrets: + # PAT_TOKEN: ${{ secrets.PAT_TOKEN }} + + # Option 3: Release to GitHub with wheel, license, and instructions bundled + # as a downloadable zip attached to the GitHub release asset. + # + # The wheel is built and packaged together with INSTRUCTIONS.txt and the + # LICENSE file into a zip that is attached directly to the GitHub release. + # Users with access to the (private) repo download the zip, follow the + # instructions inside, and install locally with pip. No PyPI or conda-forge + # upload occurs, and no docs are deployed. + # + # Choose this for private or restricted packages where distribution must be + # controlled: only users with repo access can download the release asset, + # making the GitHub release itself the distribution channel. + # + # To use: comment out Option 1 above and uncomment the lines below. + # build-release-private: + # uses: scikit-package/release-scripts/.github/workflows/_build-release-github-private-pure.yml@v0 + # with: + # project: diffpy.pdffit2 + # maintainer_github_username: sbillinge + # secrets: + # PAT_TOKEN: ${{ secrets.PAT_TOKEN }} diff --git a/.github/workflows/check-news-item.yml b/.github/workflows/check-news-item.yml index bb86a92..32130be 100644 --- a/.github/workflows/check-news-item.yml +++ b/.github/workflows/check-news-item.yml @@ -3,7 +3,7 @@ name: Check for News on: pull_request_target: branches: - - main + - main # GitHub does not evaluate expressions in trigger filters; edit this value if your base branch is not main jobs: check-news-item: diff --git a/.github/workflows/matrix-and-codecov.yml b/.github/workflows/matrix-and-codecov.yml new file mode 100644 index 0000000..4a5a830 --- /dev/null +++ b/.github/workflows/matrix-and-codecov.yml @@ -0,0 +1,21 @@ +name: Matrix and Codecov + +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.pdffit2 + c_extension: true + headless: false + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/AUTHORS.rst b/AUTHORS.rst index 23ef2b2..291f835 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -23,7 +23,7 @@ contributors. This is an open-source project and we hope and expect that the list of contributors will expand with time. Many thanks to all current and future contributors! -For more information on the DiffPy project email sb2896@columbia.edu +For more information on the DiffPy project email sb2896@ucsb.edu DiffPy was initiated as part of the Distributed Data Analysis of Neutron Scattering Experiments (DANSE) project, funded by the National Science diff --git a/CODE-OF-CONDUCT.rst b/CODE-OF-CONDUCT.rst index e8199ca..25fafe2 100644 --- a/CODE-OF-CONDUCT.rst +++ b/CODE-OF-CONDUCT.rst @@ -67,7 +67,7 @@ Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at -sb2896@columbia.edu. All complaints will be reviewed and investigated promptly and fairly. +sbillinge@ucsb.edu. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. diff --git a/LICENSE.rst b/LICENSE.rst index 092e90c..725077f 100644 --- a/LICENSE.rst +++ b/LICENSE.rst @@ -13,7 +13,7 @@ the following paper in your publication: in crystals (https://stacks.iop.org/0953-8984/19/335219), *J. Phys.: Condens. Matter*, 19, 335219 (2007) Copyright 2006-2007, Board of Trustees of Michigan State University, -Copyright 2008-2025, Board of Trustees of Columbia University in the +Copyright 2008-2026, Board of Trustees of Columbia University in the city of New York. (Copyright holder indicated in each source file). For more information please visit the project web-page: diff --git a/README.rst b/README.rst index 0adcc4b..f308a90 100644 --- a/README.rst +++ b/README.rst @@ -79,7 +79,7 @@ If you use diffpy.pdffit2 in a scientific publication, we would like you to cite Installation ------------ -diffpy.pdffit2 supports Python 3.11, 3.12, and 3.13. +diffpy.pdffit2 supports Python 3.12, 3.13, and 3.14. Windows, macOS (non-Arm64), Linux ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/cookiecutter.json b/cookiecutter.json index 174c287..8cf6acc 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -1,7 +1,9 @@ { - "maintainer_name": "Simon Billinge", - "maintainer_email": "sb2896@columbia.edu", - "maintainer_github_username": "sbillinge", + "author_names": "Simon Billinge", + "author_emails": "sbillinge@ucsb.edu", + "maintainer_names": "Simon Billinge", + "maintainer_emails": "sbillinge@ucsb.edu", + "maintainer_github_usernames": "sbillinge", "contributors": "Pavol Juhas, Chris Farrow, Simon Billinge, Billinge Group members", "license_holders": "The Trustees of Columbia University in the City of New York", "project_name": "diffpy.pdffit2", @@ -11,8 +13,8 @@ "package_dir_name": "diffpy.pdffit2", "project_short_description": "PDFfit2 - real space structure refinement program.", "project_keywords": "PDF, structure refinement", - "minimum_supported_python_version": "3.11", - "maximum_supported_python_version": "3.13", + "minimum_supported_python_version": "3.12", + "maximum_supported_python_version": "3.14", "project_needs_c_code_compiled": "Yes", "project_has_gui_tests": "No" } diff --git a/docs/source/api/diffpy.pdffit2.rst b/docs/source/api/diffpy.pdffit2.rst index 9bbc463..c36a919 100644 --- a/docs/source/api/diffpy.pdffit2.rst +++ b/docs/source/api/diffpy.pdffit2.rst @@ -13,6 +13,21 @@ Submodules ---------- +|module|:tocdepth: -1 + +|title| +======= + +.. |title| replace:: diffpy.pdffit2 package + +.. automodule:: diffpy.pdffit2 + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + diffpy.pdffit2.output module ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -36,3 +51,12 @@ diffpy.pdffit2.ipy_ext module :members: :undoc-members: :show-inheritance: + +-------- + +.. |module| replace:: diffpy.pdffit2.example_submodule module + +.. automodule:: diffpy.pdffit2.example_submodule + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/conf.py b/docs/source/conf.py index cf1514d..63a8d30 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -52,12 +52,9 @@ "sphinx.ext.intersphinx", "sphinx_rtd_theme", "sphinx_copybutton", - "m2r", + "m2r2", ] -autodoc_mock_imports = [ - "diffpy.pdffit2.pdffit2", -] # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] @@ -80,7 +77,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. diff --git a/docs/source/index.rst b/docs/source/index.rst index 866af1a..e4d7d32 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -9,6 +9,12 @@ | Software version |release| | Last updated |today|. +=============== +Getting started +=============== + +Welcome to the ``diffpy.pdffit2`` documentation! + The diffpy.pdffit2 package provides functions for the calculation and refinement of atomic Pair Distribution Functions (PDF) from crystal structure models. It is used as a computational engine by PDFgui. All @@ -88,7 +94,7 @@ Acknowledgements Table of contents ================= .. toctree:: - :titlesonly: + :maxdepth: 2 examples Package API diff --git a/pyproject.toml b/pyproject.toml index 959054d..37a27a9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,15 +6,15 @@ build-backend = "setuptools.build_meta" name = "diffpy.pdffit2" dynamic=['version', 'dependencies'] authors = [ - { name="Simon Billinge", email="sb2896@columbia.edu" }, + {name='Simon Billinge', email='sbillinge@ucsb.edu'}, ] maintainers = [ - { name="Simon Billinge", email="sb2896@columbia.edu" }, + {name='Simon Billinge', email='sbillinge@ucsb.edu'}, ] description = "PDFfit2 - real space structure refinement program." keywords = ['PDF', 'structure refinement'] readme = "README.rst" -requires-python = ">=3.11, <3.14" +requires-python = ">=3.12, <3.15" classifiers = [ 'Development Status :: 5 - Production/Stable', 'Environment :: Console', @@ -25,9 +25,9 @@ classifiers = [ 'Operating System :: Microsoft :: Windows', 'Operating System :: POSIX', 'Operating System :: Unix', - 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12', 'Programming Language :: Python :: 3.13', + 'Programming Language :: Python :: 3.14', 'Topic :: Scientific/Engineering :: Physics', 'Topic :: Scientific/Engineering :: Chemistry', ] @@ -49,7 +49,7 @@ exclude = [] # exclude packages matching these glob patterns (empty by default) namespaces = false # to disable scanning PEP 420 namespaces (true by default) [project.scripts] -diffpy-pdffit2 = "diffpy.pdffit2_app:main" +diffpy-pdffit2 = "diffpy.pdffit2.app:main" [tool.setuptools.dynamic] dependencies = {file = ["requirements/pip.txt"]} @@ -57,7 +57,12 @@ dependencies = {file = ["requirements/pip.txt"]} [tool.codespell] exclude-file = ".codespell/ignore_lines.txt" ignore-words = ".codespell/ignore_words.txt" -skip = "*.cif,*.dat,*.cc,*.h" +skip = "*.cif,*.dat" + +[tool.docformatter] +recursive = true +wrap-summaries = 72 +wrap-descriptions = 72 [tool.black] line-length = 79 diff --git a/src/diffpy/__init__.py b/src/diffpy/__init__.py index 04d8ace..0f59515 100644 --- a/src/diffpy/__init__.py +++ b/src/diffpy/__init__.py @@ -3,7 +3,7 @@ # # (c) 2008 trustees of the Michigan State University. # All rights reserved. -# (c) 2025 The Trustees of Columbia University in the City of New York. +# (c) 2025-2026 The Trustees of Columbia University in the City of New York. # All rights reserved. # # File coded by: Billinge Group members and community contributors. diff --git a/src/diffpy/pdffit2/__init__.py b/src/diffpy/pdffit2/__init__.py index 527477a..07339c9 100644 --- a/src/diffpy/pdffit2/__init__.py +++ b/src/diffpy/pdffit2/__init__.py @@ -3,10 +3,10 @@ # # (c) 2006 trustees of the Michigan State University. # All rights reserved. -# (c) 2025 The Trustees of Columbia University in the City of New York. +# (c) 2025-2026 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: Billinge group members and community contributors. # # See GitHub contributions for a more detailed list of contributors. # https://github.com/diffpy/diffpy.pdffit2/graphs/contributors diff --git a/src/diffpy/pdffit2/version.py b/src/diffpy/pdffit2/version.py index 7a1eaaa..ee14bcd 100644 --- a/src/diffpy/pdffit2/version.py +++ b/src/diffpy/pdffit2/version.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ############################################################################## # -# (c) 2025 The Trustees of Columbia University in the City of New York. +# (c) 2025-2026 The Trustees of Columbia University in the City of New York. # All rights reserved. # # File coded by: Billinge Group members and community contributors. From 78854a43de2371383ed3a266afd1a368ea907f05 Mon Sep 17 00:00:00 2001 From: Zhi Ming Xu Date: Wed, 25 Mar 2026 22:39:10 -0400 Subject: [PATCH 2/4] chore: run pre-commit on the repository --- docs/source/examples/Ni_refinement.py | 3 +- src/diffpy/pdffit2/ipy_ext.py | 4 +- src/diffpy/pdffit2/pdffit.py | 124 +++++++++++++++----------- tests/test_exceptions.py | 21 +++-- tests/test_pdffit.py | 3 +- tests/test_shape_factors.py | 12 ++- 6 files changed, 98 insertions(+), 69 deletions(-) diff --git a/docs/source/examples/Ni_refinement.py b/docs/source/examples/Ni_refinement.py index 67d93a3..d4d5d58 100755 --- a/docs/source/examples/Ni_refinement.py +++ b/docs/source/examples/Ni_refinement.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -"""Perform simple refinement of Ni structure to the experimental x-ray PDF. +"""Perform simple refinement of Ni structure to the experimental x-ray +PDF. Save fitted curve, refined structure and results summary. """ diff --git a/src/diffpy/pdffit2/ipy_ext.py b/src/diffpy/pdffit2/ipy_ext.py index ac2b547..c21f00d 100644 --- a/src/diffpy/pdffit2/ipy_ext.py +++ b/src/diffpy/pdffit2/ipy_ext.py @@ -1,7 +1,7 @@ #!/usr/bin/env python -"""This module defines functions within IPython session to simulate the old -pdffit2 interactive session. +"""This module defines functions within IPython session to simulate the +old pdffit2 interactive session. Usage: %load_ext diffpy.pdffit2.ipy_ext """ diff --git a/src/diffpy/pdffit2/pdffit.py b/src/diffpy/pdffit2/pdffit.py index 1785b38..38ddde5 100644 --- a/src/diffpy/pdffit2/pdffit.py +++ b/src/diffpy/pdffit2/pdffit.py @@ -46,7 +46,8 @@ def _format_value_std(value, stdev): def _format_bond_length(dij, ddij, ij1, symij): - """Return string with formatted bond length info for a pair of atoms. + """Return string with formatted bond length info for a pair of + atoms. dij -- distance between atoms i and j ddij -- standard deviation of dij. Ignored when small relative to dij. @@ -123,8 +124,8 @@ class PdfFit(object): Sctp = {"X": 0, "N": 1} def _exportAll(self, namespace): - """_exportAll(self, namespace) --> Export all 'public' class methods - into namespace. + """_exportAll(self, namespace) --> Export all 'public' class + methods into namespace. This function allows for a module-level PdfFit object which doesn't have to be referenced when calling a method. This @@ -193,8 +194,8 @@ def read_struct(self, struct): return def read_struct_string(self, struct, name=""): - """read_struct_string(struct, name = "") --> Read structure from a - string into memory. + """read_struct_string(struct, name = "") --> Read structure from + a string into memory. struct -- string containing the contents of the structure file name -- tag with which to label structure @@ -209,8 +210,8 @@ def read_struct_string(self, struct, name=""): return def read_data(self, data, stype, qmax, qdamp): - """read_data(data, stype, qmax, qdamp) --> Read pdf data from file into - memory. + """read_data(data, stype, qmax, qdamp) --> Read pdf data from + file into memory. data -- name of file from which to read data stype -- 'X' (xray) or 'N' (neutron) @@ -224,8 +225,8 @@ def read_data(self, data, stype, qmax, qdamp): return def read_data_string(self, data, stype, qmax, qdamp, name=""): - """read_data_string(data, stype, qmax, qdamp, name = "") --> Read pdf - data from a string into memory. + """read_data_string(data, stype, qmax, qdamp, name = "") --> + Read pdf data from a string into memory. data -- string containing the contents of the data file stype -- 'X' (xray) or 'N' (neutron) @@ -243,8 +244,8 @@ def read_data_string(self, data, stype, qmax, qdamp, name=""): def read_data_lists( self, stype, qmax, qdamp, r_data, Gr_data, dGr_data=None, name="list" ): - """read_data_lists(stype, qmax, qdamp, r_data, Gr_data, dGr_data = - None, name = "list") --> Read pdf data into memory from lists. + """read_data_lists(stype, qmax, qdamp, r_data, Gr_data, dGr_data + = None, name = "list") --> Read pdf data into memory from lists. All lists must be of the same length. stype -- 'X' (xray) or 'N' (neutron) @@ -283,15 +284,16 @@ def pdfrange(self, iset, rmin, rmax): return def reset(self): - """Reset() --> Clear all stored fit, structure, and parameter data.""" + """Reset() --> Clear all stored fit, structure, and parameter + data.""" self.stru_files = [] self.data_files = [] pdffit2.reset(self._handle) return def alloc(self, stype, qmax, qdamp, rmin, rmax, bin): - """Alloc(stype, qmax, qdamp, rmin, rmax, bin) --> Allocate space for a - PDF calculation. + """Alloc(stype, qmax, qdamp, rmin, rmax, bin) --> Allocate space + for a PDF calculation. The structure from which to calculate the PDF must first be imported with the read_struct() or read_struct_string() method. @@ -328,7 +330,8 @@ def calc(self): return def refine(self, toler=0.00000001): - """Refine(toler = 0.00000001) --> Fit the theory to the imported data. + """Refine(toler = 0.00000001) --> Fit the theory to the imported + data. toler -- tolerance of the fit @@ -347,7 +350,8 @@ def refine(self, toler=0.00000001): return def refine_step(self, toler=0.00000001): - """refine_step(toler = 0.00000001) --> Run a single step of the fit. + """refine_step(toler = 0.00000001) --> Run a single step of the + fit. toler -- tolerance of the fit @@ -364,7 +368,8 @@ def refine_step(self, toler=0.00000001): return self.finished def save_pdf(self, iset, fname): - """save_pdf(iset, fname) --> Save calculated or fitted PDF to file. + """save_pdf(iset, fname) --> Save calculated or fitted PDF to + file. iset -- data set to save @@ -376,7 +381,8 @@ def save_pdf(self, iset, fname): return def save_pdf_string(self, iset): - """save_pdf_string(iset) --> Save calculated or fitted PDF to string. + """save_pdf_string(iset) --> Save calculated or fitted PDF to + string. iset -- data set to save @@ -389,8 +395,8 @@ def save_pdf_string(self, iset): return pdffilestring def save_dif(self, iset, fname): - """save_dif(iset, fname) --> Save data and fitted PDF difference to - file. + """save_dif(iset, fname) --> Save data and fitted PDF difference + to file. iset -- data set to save @@ -402,8 +408,8 @@ def save_dif(self, iset, fname): return def save_dif_string(self, iset): - """save_dif_string(iset) --> Save data and fitted PDF difference to - string. + """save_dif_string(iset) --> Save data and fitted PDF difference + to string. iset -- data set to save @@ -452,8 +458,8 @@ def get_structure(self, ip): return stru def save_struct(self, ip, fname): - """save_struct(ip, fname) --> Save structure resulting from fit to - file. + """save_struct(ip, fname) --> Save structure resulting from fit + to file. ip -- phase to save @@ -465,7 +471,8 @@ def save_struct(self, ip, fname): return def save_struct_string(self, ip): - """save_struct(ip) --> Save structure resulting from fit to string. + """save_struct(ip) --> Save structure resulting from fit to + string. ip -- phase to save @@ -488,7 +495,8 @@ def show_struct(self, ip): return def constrain(self, var, par, fcon=None): - """Constrain(var, par[, fcon]) --> Constrain a variable to a parameter. + """Constrain(var, par[, fcon]) --> Constrain a variable to a + parameter. A variable can be constrained to a number or equation string. @@ -648,7 +656,8 @@ def getpdf_diff(self): return Gdiff def get_atoms(self, ip=None): - """get_atoms() --> Get element symbols of all atoms in the structure. + """get_atoms() --> Get element symbols of all atoms in the + structure. ip -- index of phase to get the elements from (starting from 1) when ip is not given, use current phase @@ -754,7 +763,8 @@ def psel(self, ip): return def pdesel(self, ip): - """Pdesel(ip) --> Exclude phase ip from calculation of total PDF. + """Pdesel(ip) --> Exclude phase ip from calculation of total + PDF. pdesel('ALL') excludes all phases from PDF calculation. @@ -851,9 +861,9 @@ def bang(self, i, j, k): return def bond_angle(self, i, j, k): - """bond_angle(i, j, k) --> bond angle defined by atoms i, j, k. Angle - is calculated using the shortest ji and jk lengths with respect to - periodic boundary conditions. + """bond_angle(i, j, k) --> bond angle defined by atoms i, j, k. + Angle is calculated using the shortest ji and jk lengths with + respect to periodic boundary conditions. i, j, k -- atom indices starting at 1 @@ -942,8 +952,9 @@ def blen(self, *args): return def bond_length_atoms(self, i, j): - """bond_length_atoms(i, j) --> shortest distance between atoms i, j. - Periodic boundary conditions are applied to find the shortest bond. + """bond_length_atoms(i, j) --> shortest distance between atoms + i, j. Periodic boundary conditions are applied to find the + shortest bond. i -- index of the first atom starting at 1 j -- index of the second atom starting at 1 @@ -957,7 +968,8 @@ def bond_length_atoms(self, i, j): return rv def bond_length_types(self, a1, a2, lb, ub): - """bond_length_types(a1, a2, lb, ub) --> get all a1-a2 distances. + """bond_length_types(a1, a2, lb, ub) --> get all a1-a2 + distances. a1 -- symbol of the first element in pair or "ALL" a2 -- symbol of the second element in pair or "ALL" @@ -978,8 +990,8 @@ def bond_length_types(self, a1, a2, lb, ub): return rv def show_scat(self, stype): - """show_scat(stype) --> Print scattering length for all atoms in the - current phase. + """show_scat(stype) --> Print scattering length for all atoms in + the current phase. stype -- 'X' (xray) or 'N' (neutron). @@ -989,8 +1001,8 @@ def show_scat(self, stype): return def get_scat_string(self, stype): - """get_scat_string(stype) --> Get string with scattering factors of all - atoms in the current phase. + """get_scat_string(stype) --> Get string with scattering factors + of all atoms in the current phase. stype -- 'X' (xray) or 'N' (neutron). @@ -1002,10 +1014,10 @@ def get_scat_string(self, stype): return pdffit2.get_scat_string(self._handle, stype.encode()) def get_scat(self, stype, element): - """get_scat(stype, element) --> Get active scattering factor for given - element. If scattering factor has been changed using set_scat the - result may depend on the active phase. When no phase has been loaded, - return the standard value. + """get_scat(stype, element) --> Get active scattering factor for + given element. If scattering factor has been changed using + set_scat the result may depend on the active phase. When no + phase has been loaded, return the standard value. stype -- 'X' (xray) or 'N' (neutron). element -- case-insensitive element symbol such as "Na" or "CL" @@ -1019,9 +1031,10 @@ def get_scat(self, stype, element): return rv def set_scat(self, stype, element, value): - """set_scat(stype, element, value) --> Set custom scattering factor for - given element. The new scattering factor applies only for the current - phase, in other phases it keeps its default value. + """set_scat(stype, element, value) --> Set custom scattering + factor for given element. The new scattering factor applies + only for the current phase, in other phases it keeps its default + value. stype -- 'X' (xray) or 'N' (neutron). element -- case-insensitive element symbol such as "Na" or "CL" @@ -1039,9 +1052,9 @@ def set_scat(self, stype, element, value): return def reset_scat(self, element): - """reset_scat(stype, element) --> Reset scattering factors for given - element to their standard values. The reset_scat applies only for the - current phase. + """reset_scat(stype, element) --> Reset scattering factors for + given element to their standard values. The reset_scat applies + only for the current phase. element -- case-insensitive element symbol such as "Na" or "CL" Raises: @@ -1069,7 +1082,8 @@ def num_phases(self): return n def num_datasets(self): - """num_datasets() --> Number of datasets loaded in PdfFit instance. + """num_datasets() --> Number of datasets loaded in PdfFit + instance. Use setdata to bring a specific dataset in focus. @@ -1079,9 +1093,9 @@ def num_datasets(self): return n def phase_fractions(self): - """phase_fractions() --> relative phase fractions for current dataset. - Convert phase scale factors to relative phase fractions given the - scattering type of current dataset. + """phase_fractions() --> relative phase fractions for current + dataset. Convert phase scale factors to relative phase fractions + given the scattering type of current dataset. Return a dictionary of phase fractions with following keys: @@ -1254,7 +1268,8 @@ def qbroad(): qbroad = staticmethod(qbroad) def spdiameter(): - """Spdiameter() --> Get reference to spdiameter (phase property). + """Spdiameter() --> Get reference to spdiameter (phase + property). Diameter value for the spherical particle PDF correction. Spherical envelope is not applied when spdiameter equals 0. @@ -1307,7 +1322,8 @@ def __init__(self, create_intro=True): return def __getRef(self, var_string): - """Return the actual reference to the variable in the var_string. + """Return the actual reference to the variable in the + var_string. This function must be called before trying to actually reference an internal variable. See the constrain method for an example. diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index 07a4f4e..58272d9 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -46,7 +46,8 @@ def test_structureError(self): ) def test_structureErrorZeroVolume(self): - """Raise pdffit2.structureError when unit cell volume is negative.""" + """Raise pdffit2.structureError when unit cell volume is + negative.""" # I don't know how to test for this, but it's in the library code self.assertRaises( pdffit2.structureError, @@ -312,7 +313,8 @@ def tearDown(self): del self.P def test_unassignedError(self): - """Raise pdffit2.unassignedError when no space has been allocated.""" + """Raise pdffit2.unassignedError when no space has been + allocated.""" self.assertRaises(pdffit2.unassignedError, self.P.calc) @@ -647,11 +649,13 @@ def tearDown(self): del self.P def test_unassignedError1(self): - """Raise pdffit2.unassignedError when parameter does not exist.""" + """Raise pdffit2.unassignedError when parameter does not + exist.""" self.assertRaises(pdffit2.unassignedError, self.P.getpar, 1) def test_unassignedError2(self): - """Raise pdffit2.unassignedError when parameter does not exist.""" + """Raise pdffit2.unassignedError when parameter does not + exist.""" self.P.read_struct(self.datafile("Ni.stru")) self.P.constrain(self.P.lat(1), 2) self.assertRaises(pdffit2.unassignedError, self.P.getpar, 1) @@ -985,7 +989,8 @@ def tearDown(self): del self.P def test_unassignedError(self): - """Raise pdffit2.unassignedError when parameter does not exist.""" + """Raise pdffit2.unassignedError when parameter does not + exist.""" self.P.read_struct(self.datafile("Ni.stru")) self.P.read_data(self.datafile("Ni.dat"), "X", 25.0, 0.0) self.assertRaises(pdffit2.unassignedError, self.P.fixpar, 1) @@ -1003,7 +1008,8 @@ def tearDown(self): del self.P def test_unassignedError(self): - """Raise pdffit2.unassignedError when parameter does not exist.""" + """Raise pdffit2.unassignedError when parameter does not + exist.""" self.P.read_struct(self.datafile("Ni.stru")) self.P.read_data(self.datafile("Ni.dat"), "X", 25.0, 0.0) self.assertRaises(pdffit2.unassignedError, self.P.freepar, 1) @@ -1039,7 +1045,8 @@ def tearDown(self): del self.P def test_unassignedError(self): - """Raise pdffit2.unassignedError when data set does not exist.""" + """Raise pdffit2.unassignedError when data set does not + exist.""" self.P.read_struct(self.datafile("Ni.stru")) self.P.read_data(self.datafile("Ni.dat"), "X", 25.0, 0.0) self.assertRaises(pdffit2.unassignedError, self.P.setdata, 2) diff --git a/tests/test_pdffit.py b/tests/test_pdffit.py index 54b1a1c..e6823da 100644 --- a/tests/test_pdffit.py +++ b/tests/test_pdffit.py @@ -341,7 +341,8 @@ def test_getcrw(self): return def test_getcrw_two_datasets(self): - """Check that getcrw() and getrw() are consistent for two datasets.""" + """Check that getcrw() and getrw() are consistent for two + datasets.""" self.P.read_data(self.datafile("Ni.dat"), "X", 25.0, 0.0) self.P.pdfrange(1, 2, 8) self.P.read_data(self.datafile("300K.gr"), "N", 32.0, 0.0) diff --git a/tests/test_shape_factors.py b/tests/test_shape_factors.py index 70424e5..ee61c9a 100644 --- a/tests/test_shape_factors.py +++ b/tests/test_shape_factors.py @@ -83,7 +83,8 @@ def test_refinement(self): return def test_twophase_calculation(self): - """Check PDF calculation for 2 phases with different spdiameters.""" + """Check PDF calculation for 2 phases with different + spdiameters.""" d1 = 6 d2 = 9 self.P.read_struct(self.datafile("Ni.stru")) @@ -114,7 +115,8 @@ def test_twophase_calculation(self): return def test_twophase_refinement(self): - """Check PDF refinement of 2 phases that have different spdiameter.""" + """Check PDF refinement of 2 phases that have different + spdiameter.""" dcheck1 = 8.0 dstart1 = 8.2 dcheck2 = 6.0 @@ -153,7 +155,8 @@ def test_twophase_refinement(self): return def test_spdiameter_io(self): - """Check reading and writing of spdiameter from structure file.""" + """Check reading and writing of spdiameter from structure + file.""" import re self.P.read_struct(self.datafile("Ni.stru")) @@ -218,7 +221,8 @@ def test_stepcut_calculation(self): return def test_twophase_stepcut_calculation(self): - """Check PDF calculation for 2 phases with different spdiameters.""" + """Check PDF calculation for 2 phases with different + spdiameters.""" d1 = 6 d2 = 9 self.P.read_struct(self.datafile("Ni.stru")) From 511fc9f76b62c78487dcd9b35f3e89492280990a Mon Sep 17 00:00:00 2001 From: Zhi Ming Xu Date: Wed, 25 Mar 2026 22:47:45 -0400 Subject: [PATCH 3/4] chore: make minor fixes --- AUTHORS.rst | 2 +- docs/source/api/diffpy.pdffit2.rst | 24 ------------------------ pyproject.toml | 2 +- 3 files changed, 2 insertions(+), 26 deletions(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index 291f835..21affc2 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -23,7 +23,7 @@ contributors. This is an open-source project and we hope and expect that the list of contributors will expand with time. Many thanks to all current and future contributors! -For more information on the DiffPy project email sb2896@ucsb.edu +For more information on the DiffPy project email sbillinge@ucsb.edu DiffPy was initiated as part of the Distributed Data Analysis of Neutron Scattering Experiments (DANSE) project, funded by the National Science diff --git a/docs/source/api/diffpy.pdffit2.rst b/docs/source/api/diffpy.pdffit2.rst index c36a919..9bbc463 100644 --- a/docs/source/api/diffpy.pdffit2.rst +++ b/docs/source/api/diffpy.pdffit2.rst @@ -13,21 +13,6 @@ Submodules ---------- -|module|:tocdepth: -1 - -|title| -======= - -.. |title| replace:: diffpy.pdffit2 package - -.. automodule:: diffpy.pdffit2 - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - diffpy.pdffit2.output module ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -51,12 +36,3 @@ diffpy.pdffit2.ipy_ext module :members: :undoc-members: :show-inheritance: - --------- - -.. |module| replace:: diffpy.pdffit2.example_submodule module - -.. automodule:: diffpy.pdffit2.example_submodule - :members: - :undoc-members: - :show-inheritance: diff --git a/pyproject.toml b/pyproject.toml index 37a27a9..0722d4e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,7 +49,7 @@ exclude = [] # exclude packages matching these glob patterns (empty by default) namespaces = false # to disable scanning PEP 420 namespaces (true by default) [project.scripts] -diffpy-pdffit2 = "diffpy.pdffit2.app:main" +diffpy-pdffit2 = "diffpy.pdffit2_app:main" [tool.setuptools.dynamic] dependencies = {file = ["requirements/pip.txt"]} From 94cabbe4cc90af4cf2533f273b0c08251b7a6a5e Mon Sep 17 00:00:00 2001 From: Zhi Ming Xu Date: Thu, 26 Mar 2026 14:34:33 -0400 Subject: [PATCH 4/4] chore: add back autodoc and .cc and .h skips for codespell --- docs/source/conf.py | 4 ++++ pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 63a8d30..9de6b62 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -55,6 +55,10 @@ "m2r2", ] +autodoc_mock_imports = [ + "diffpy.pdffit2.pdffit2", +] + # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] diff --git a/pyproject.toml b/pyproject.toml index 0722d4e..394308b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,7 +57,7 @@ dependencies = {file = ["requirements/pip.txt"]} [tool.codespell] exclude-file = ".codespell/ignore_lines.txt" ignore-words = ".codespell/ignore_words.txt" -skip = "*.cif,*.dat" +skip = "*.cif,*.dat,*.cc,*.h" [tool.docformatter] recursive = true