From ce58e72d2274d1a22ed872f033dfc32bd36182ad Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Wed, 4 Nov 2026 10:55:03 -0500 Subject: [PATCH 1/4] chore: update Simon Billinge's contact email to sbillinge@ucsb.edu Update the address in CODE-OF-CONDUCT.rst, README.rst and the authors and maintainers in pyproject.toml. Co-Authored-By: Claude Opus 5.5 --- CODE-OF-CONDUCT.rst | 2 +- README.rst | 2 +- pyproject.toml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) 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/README.rst b/README.rst index e7ee53b..24171d7 100644 --- a/README.rst +++ b/README.rst @@ -195,7 +195,7 @@ Before contributing, please read our `Code of Conduct `_ or email Simon Billinge at sb2896@columbia.edu. +For more information on diffpy.cmi please visit the project `web-page `_ or email Simon Billinge at sbillinge@ucsb.edu. Acknowledgements ---------------- diff --git a/pyproject.toml b/pyproject.toml index e65cd81..322ea98 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,10 +6,10 @@ build-backend = "setuptools.build_meta" name = "diffpy.cmi" 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 = "Complex modeling infrastructure: a modular framework for multi-modal modeling of scientific data." keywords = ['modelling', 'regression', 'diffraction', 'PDF', 'complex-modeling'] From 1340af9d2e1c1f4759b34c73b34f5c99c3b0c245 Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Wed, 4 Nov 2026 10:55:05 -0500 Subject: [PATCH 2/4] fix: make diffpy a pkgutil-style namespace package Extend diffpy.__path__ in src/diffpy/__init__.py so that diffpy.cmi can be imported alongside the other diffpy packages. Co-Authored-By: Claude Opus 5.5 --- src/diffpy/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/diffpy/__init__.py b/src/diffpy/__init__.py index fb00aa5..9714a78 100644 --- a/src/diffpy/__init__.py +++ b/src/diffpy/__init__.py @@ -12,3 +12,7 @@ # See LICENSE.rst for license information. # ############################################################################## + +from pkgutil import extend_path + +__path__ = extend_path(__path__, __name__) From fb1ffd4878c24a363f082827f9d1815dab5184e1 Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Wed, 4 Nov 2026 10:55:10 -0500 Subject: [PATCH 3/4] chore: close the figures of each example in validate_examples.py Close all matplotlib figures after running each example so that figures don't pile up while the examples are validated. Co-Authored-By: Claude Opus 5.5 --- validators/validate_examples.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/validators/validate_examples.py b/validators/validate_examples.py index 3fd2cde..5b9f789 100644 --- a/validators/validate_examples.py +++ b/validators/validate_examples.py @@ -2,6 +2,7 @@ import shutil from pathlib import Path +import matplotlib.pyplot as plt import pytest PROJECT_ROOT = Path(__file__).resolve().parents[1] @@ -30,3 +31,4 @@ def test_all_examples(tmp_examples): script_relative_path = script.relative_to(tmp_examples) print(f"Testing {script_relative_path}") runpy.run_path(str(script), run_name="__main__") + plt.close("all") From 5c0f27b66ea39bc2d05fa3cfca1db939c790b235 Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Wed, 4 Nov 2026 10:55:14 -0500 Subject: [PATCH 4/4] docs: print the fit results of the examples with print_results_table Replace FitResults.print_results with print_results_table in every example script and notebook in docs/examples, so users see the results as tables with the variables grouped by tag. The SimpleRecipe example calls recipe.results.print_results_table(update=True), since SimpleRecipe has no print_results_table of its own. Add the news item for the branch. Co-Authored-By: Claude Opus 5.5 --- docs/examples/core/debye-waller/debyemodel.py | 2 +- .../core/debye-waller/debyemodelII.py | 2 +- .../core/gaussianfit/gaussianrecipe.py | 2 +- docs/examples/core/gaussianfit/interface.py | 2 +- .../examples/core/gaussianfit/simplerecipe.py | 2 +- .../core/gaussianfit/threedoublepeaks.py | 2 +- .../examples/core/intensityfit/npintensity.py | 2 +- .../core/intensityfit/npintensityII.py | 2 +- .../exercises/diffpy-cmi/fitBulkNi.ipynb | 4 ++-- .../exercises/diffpy-cmi/fitNPPt.ipynb | 2 +- .../solutions/diffpy-cmi/fitBulkNi.py | 4 ++-- .../solutions/diffpy-cmi/fitNPPt.py | 2 +- .../solutions/diffpy-cmi/fit2P.py | 2 +- .../solutions/diffpy-cmi/fitCrystalGen.py | 2 +- .../solutions/diffpy-cmi/fitTSeries.py | 2 +- .../solutions/diffpy-cmi/fitCdSeNP.py | 4 ++-- .../solutions/diffpy-cmi/fitCdSeNP.py | 2 +- .../pdf/nanoparticle-fit/coreshellnp.py | 2 +- news/print-results-table.rst | 24 +++++++++++++++++++ 19 files changed, 45 insertions(+), 21 deletions(-) create mode 100644 news/print-results-table.rst diff --git a/docs/examples/core/debye-waller/debyemodel.py b/docs/examples/core/debye-waller/debyemodel.py index c01b5f2..cfab6dd 100644 --- a/docs/examples/core/debye-waller/debyemodel.py +++ b/docs/examples/core/debye-waller/debyemodel.py @@ -169,7 +169,7 @@ def main(): res = FitResults(recipe) # Print the results - res.print_results() + res.print_results_table() # Plot the results recipe.plot_recipe( diff --git a/docs/examples/core/debye-waller/debyemodelII.py b/docs/examples/core/debye-waller/debyemodelII.py index 107add0..5338e10 100644 --- a/docs/examples/core/debye-waller/debyemodelII.py +++ b/docs/examples/core/debye-waller/debyemodelII.py @@ -139,7 +139,7 @@ def main(): res = FitResults(recipe) # Print the results - res.print_results() + res.print_results_table() # Plot the results plot_results(recipe) diff --git a/docs/examples/core/gaussianfit/gaussianrecipe.py b/docs/examples/core/gaussianfit/gaussianrecipe.py index 3881f17..d8e195d 100644 --- a/docs/examples/core/gaussianfit/gaussianrecipe.py +++ b/docs/examples/core/gaussianfit/gaussianrecipe.py @@ -70,7 +70,7 @@ def main(): res = FitResults(recipe) # Print the results. - res.print_results() + res.print_results_table() # Plot the results. recipe.plot_recipe() diff --git a/docs/examples/core/gaussianfit/interface.py b/docs/examples/core/gaussianfit/interface.py index 8ffae34..fd55bdc 100644 --- a/docs/examples/core/gaussianfit/interface.py +++ b/docs/examples/core/gaussianfit/interface.py @@ -66,7 +66,7 @@ def main(): res = FitResults(r) # Print the results. - res.print_results() + res.print_results_table() # Plot the results. r.plot_recipe(xlabel="x", ylabel="y") diff --git a/docs/examples/core/gaussianfit/simplerecipe.py b/docs/examples/core/gaussianfit/simplerecipe.py index fc36c0d..2c2de37 100644 --- a/docs/examples/core/gaussianfit/simplerecipe.py +++ b/docs/examples/core/gaussianfit/simplerecipe.py @@ -53,7 +53,7 @@ def main(): leastsq(recipe.residual, recipe.values) # Print the results - recipe.print_results() + recipe.results.print_results_table(update=True) return diff --git a/docs/examples/core/gaussianfit/threedoublepeaks.py b/docs/examples/core/gaussianfit/threedoublepeaks.py index a62fc36..e793493 100644 --- a/docs/examples/core/gaussianfit/threedoublepeaks.py +++ b/docs/examples/core/gaussianfit/threedoublepeaks.py @@ -190,5 +190,5 @@ def steer_fit(recipe): recipe = make_recipe() steer_fit(recipe) res = FitResults(recipe) - res.print_results() + res.print_results_table() recipe.plot_recipe() diff --git a/docs/examples/core/intensityfit/npintensity.py b/docs/examples/core/intensityfit/npintensity.py index 9e4c8fd..4dee62c 100644 --- a/docs/examples/core/intensityfit/npintensity.py +++ b/docs/examples/core/intensityfit/npintensity.py @@ -327,7 +327,7 @@ def main(): rescount = recipe.fithooks[0].count calcount = recipe.bucky.I.count footer = "iofq called %i%% of the time" % int(100.0 * calcount / rescount) - res.print_results(footer=footer) + res.print_results_table(footer=footer) # Plot! plot_results(recipe) diff --git a/docs/examples/core/intensityfit/npintensityII.py b/docs/examples/core/intensityfit/npintensityII.py index 6400fea..de624bf 100644 --- a/docs/examples/core/intensityfit/npintensityII.py +++ b/docs/examples/core/intensityfit/npintensityII.py @@ -258,7 +258,7 @@ def main(): # Generate and print the FitResults res = FitResults(recipe) - res.print_results() + res.print_results_table() # Plot! plot_results(recipe) diff --git a/docs/examples/pdf/ch03NiModelling/exercises/diffpy-cmi/fitBulkNi.ipynb b/docs/examples/pdf/ch03NiModelling/exercises/diffpy-cmi/fitBulkNi.ipynb index 7e578ea..33b15f4 100644 --- a/docs/examples/pdf/ch03NiModelling/exercises/diffpy-cmi/fitBulkNi.ipynb +++ b/docs/examples/pdf/ch03NiModelling/exercises/diffpy-cmi/fitBulkNi.ipynb @@ -504,10 +504,10 @@ " profile.savetxt(fitdir / f\"{basename}.fit\")\n", "\n", " # 26: We use the 'FitResults' method to parse out the results from\n", - " # the optimized Fit Recipe, and 'print_results' to print them\n", + " # the optimized Fit Recipe, and 'print_results_table' to print them\n", " # to the terminal.\n", " res = FitResults(recipe)\n", - " res.print_results()\n", + " res.print_results_table()\n", "\n", " # 27: We use the 'save_results' method of 'FitResults' to write a text file\n", " # containing the fitted parameters and fit quality indices to disk.\n", diff --git a/docs/examples/pdf/ch03NiModelling/exercises/diffpy-cmi/fitNPPt.ipynb b/docs/examples/pdf/ch03NiModelling/exercises/diffpy-cmi/fitNPPt.ipynb index a464aca..6951906 100644 --- a/docs/examples/pdf/ch03NiModelling/exercises/diffpy-cmi/fitNPPt.ipynb +++ b/docs/examples/pdf/ch03NiModelling/exercises/diffpy-cmi/fitNPPt.ipynb @@ -409,7 +409,7 @@ "\n", " # 27 Print the fit results to the terminal.\n", " res = FitResults(recipe)\n", - " res.print_results()\n", + " res.print_results_table()\n", "\n", " # 28 Write the fit results to a file.\n", " header = \"crystal_HF.\\n\"\n", diff --git a/docs/examples/pdf/ch03NiModelling/solutions/diffpy-cmi/fitBulkNi.py b/docs/examples/pdf/ch03NiModelling/solutions/diffpy-cmi/fitBulkNi.py index f6be5e1..5cd38a7 100644 --- a/docs/examples/pdf/ch03NiModelling/solutions/diffpy-cmi/fitBulkNi.py +++ b/docs/examples/pdf/ch03NiModelling/solutions/diffpy-cmi/fitBulkNi.py @@ -297,10 +297,10 @@ def main(): profile.savetxt(fitdir / f"{basename}.fit") # 26: We use the 'FitResults' method to parse out the results from - # the optimized Fit Recipe, and 'printResults' to print them + # the optimized Fit Recipe, and 'print_results_table' to print them # to the terminal. res = FitResults(recipe) - res.print_results() + res.print_results_table() # 27: We use the 'saveResults' method of 'FitResults' to write a text file # containing the fitted parameters and fit quality indices to disk. diff --git a/docs/examples/pdf/ch03NiModelling/solutions/diffpy-cmi/fitNPPt.py b/docs/examples/pdf/ch03NiModelling/solutions/diffpy-cmi/fitNPPt.py index 981d03c..41c8eeb 100644 --- a/docs/examples/pdf/ch03NiModelling/solutions/diffpy-cmi/fitNPPt.py +++ b/docs/examples/pdf/ch03NiModelling/solutions/diffpy-cmi/fitNPPt.py @@ -263,7 +263,7 @@ def main(): # 27 Print the fit results to the terminal. res = FitResults(recipe) - res.print_results() + res.print_results_table() # 28 Write the fit results to a file. header = "crystal_HF.\n" diff --git a/docs/examples/pdf/ch05Fit2Phase/solutions/diffpy-cmi/fit2P.py b/docs/examples/pdf/ch05Fit2Phase/solutions/diffpy-cmi/fit2P.py index eed99ef..c82ae4c 100644 --- a/docs/examples/pdf/ch05Fit2Phase/solutions/diffpy-cmi/fit2P.py +++ b/docs/examples/pdf/ch05Fit2Phase/solutions/diffpy-cmi/fit2P.py @@ -387,7 +387,7 @@ def main(): # 24 Print the fit results to the terminal. res = FitResults(recipe) - res.print_results() + res.print_results_table() # 25 Write the fit results to a file. header = "crystal_HF.\n" diff --git a/docs/examples/pdf/ch06RefineCrystalStructureGen/solutions/diffpy-cmi/fitCrystalGen.py b/docs/examples/pdf/ch06RefineCrystalStructureGen/solutions/diffpy-cmi/fitCrystalGen.py index c63fe52..2a76b09 100644 --- a/docs/examples/pdf/ch06RefineCrystalStructureGen/solutions/diffpy-cmi/fitCrystalGen.py +++ b/docs/examples/pdf/ch06RefineCrystalStructureGen/solutions/diffpy-cmi/fitCrystalGen.py @@ -262,7 +262,7 @@ def main(): # 29: Print the fit results to the terminal. res = FitResults(recipe) - res.print_results() + res.print_results_table() # 30: Write the fit results to a file. header = "crystal_HF.\n" diff --git a/docs/examples/pdf/ch07StructuralPhaseTransitions/solutions/diffpy-cmi/fitTSeries.py b/docs/examples/pdf/ch07StructuralPhaseTransitions/solutions/diffpy-cmi/fitTSeries.py index d675a77..5449f61 100644 --- a/docs/examples/pdf/ch07StructuralPhaseTransitions/solutions/diffpy-cmi/fitTSeries.py +++ b/docs/examples/pdf/ch07StructuralPhaseTransitions/solutions/diffpy-cmi/fitTSeries.py @@ -274,7 +274,7 @@ def main(): # 34: Print the fit results to the terminal. res = FitResults(recipe) - res.print_results() + res.print_results_table() # 35: Write the fit results to a file. header = "crystal_HF.\n" diff --git a/docs/examples/pdf/ch08NPRefinement/solutions/diffpy-cmi/fitCdSeNP.py b/docs/examples/pdf/ch08NPRefinement/solutions/diffpy-cmi/fitCdSeNP.py index f28168e..8b1e992 100644 --- a/docs/examples/pdf/ch08NPRefinement/solutions/diffpy-cmi/fitCdSeNP.py +++ b/docs/examples/pdf/ch08NPRefinement/solutions/diffpy-cmi/fitCdSeNP.py @@ -494,7 +494,7 @@ def main(): # 58: Print the fit results to the terminal. res = FitResults(recipe) - res.print_results() + res.print_results_table() # 59: Write the fit results to a file. header = "crystal_HF.\n" @@ -571,7 +571,7 @@ def main(): # 68: Print the fit results to the terminal. res = FitResults(recipe) - res.print_results() + res.print_results_table() # 69: Write the fit results to a file. header = "crystal_HF.\n" diff --git a/docs/examples/pdf/ch11ClusterXYZ/solutions/diffpy-cmi/fitCdSeNP.py b/docs/examples/pdf/ch11ClusterXYZ/solutions/diffpy-cmi/fitCdSeNP.py index d541418..f03a0e5 100644 --- a/docs/examples/pdf/ch11ClusterXYZ/solutions/diffpy-cmi/fitCdSeNP.py +++ b/docs/examples/pdf/ch11ClusterXYZ/solutions/diffpy-cmi/fitCdSeNP.py @@ -225,7 +225,7 @@ def main(): # Print the fit results to the terminal. res = FitResults(recipe) - res.print_results() + res.print_results_table() # Write the fit results to a file. header = "crystal_HF.\n" diff --git a/docs/examples/pdf/nanoparticle-fit/coreshellnp.py b/docs/examples/pdf/nanoparticle-fit/coreshellnp.py index 92b6f9b..c4f4075 100644 --- a/docs/examples/pdf/nanoparticle-fit/coreshellnp.py +++ b/docs/examples/pdf/nanoparticle-fit/coreshellnp.py @@ -182,7 +182,7 @@ def main(): # Generate and print the FitResults res = FitResults(recipe) - res.print_results() + res.print_results_table() # Plot! recipe.plot_recipe(xlabel=r"$r (\AA)$", ylabel=r"$G (\AA^{-2})$") diff --git a/news/print-results-table.rst b/news/print-results-table.rst new file mode 100644 index 0000000..1558170 --- /dev/null +++ b/news/print-results-table.rst @@ -0,0 +1,24 @@ +**Added:** + +* + +**Changed:** + +* Simon Billinge's contact email to sbillinge@ucsb.edu. +* The examples print their fit results with ``FitResults.print_results_table``, which shows them as tables with the variables grouped by tag. + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* ``diffpy`` is a pkgutil-style namespace package, so ``diffpy.cmi`` can be imported alongside other ``diffpy`` packages. + +**Security:** + +*