diffpy.apps 0.2.0rc0__tar.gz → 0.2.0rc2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {diffpy_apps-0.2.0rc0/src/diffpy.apps.egg-info → diffpy_apps-0.2.0rc2}/PKG-INFO +5 -5
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/pyproject.toml +3 -4
- diffpy_apps-0.2.0rc2/src/diffpy/__init__.py +14 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/src/diffpy/apps/app_agentify.py +22 -12
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/src/diffpy/apps/pdfadapter.py +7 -6
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/src/diffpy/apps/refinebase/parametric_model.py +8 -9
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/src/diffpy/apps/refinebase/refinement_server.py +22 -30
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/src/diffpy/apps/refinebase/refinement_session.py +2 -2
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2/src/diffpy.apps.egg-info}/PKG-INFO +5 -5
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/tests/conftest.py +1 -1
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/tests/helper.py +18 -18
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/tests/test_agentify.py +9 -6
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/tests/test_pdfadapter.py +3 -1
- diffpy_apps-0.2.0rc0/src/diffpy/apps/refinebase/__init__.py +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/AUTHORS.rst +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/LICENSE.rst +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/MANIFEST.in +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/README.rst +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/requirements/build.txt +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/requirements/conda.txt +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/requirements/docs.txt +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/requirements/pip.txt +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/requirements/tests.txt +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/setup.cfg +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/src/diffpy/apps/__init__.py +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/src/diffpy/apps/app_runmacro.py +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/src/diffpy/apps/apps.py +0 -0
- {diffpy_apps-0.2.0rc0/src/diffpy → diffpy_apps-0.2.0rc2/src/diffpy/apps/refinebase}/__init__.py +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/src/diffpy/apps/version.py +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/src/diffpy.apps.egg-info/SOURCES.txt +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/src/diffpy.apps.egg-info/dependency_links.txt +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/src/diffpy.apps.egg-info/entry_points.txt +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/src/diffpy.apps.egg-info/requires.txt +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/src/diffpy.apps.egg-info/top_level.txt +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/tests/data/C60.gr +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/tests/data/Ni.cif +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/tests/data/Ni.gr +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/tests/data/c60xyz.txt +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/tests/data/make_c60.txt +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/tests/data/ni-q27r100-neutron.gr +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/tests/data/ni-q27r60-xray.gr +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/tests/data/pb.cif +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/tests/data/pb_100_qmin1.gr +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/tests/data/si-q27r60-xray.gr +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/tests/data/si.cif +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/tests/data/si90ni10-q27r60-xray.gr +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/tests/data/sine.dat +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/tests/test_parametric_model.py +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/tests/test_refinement_server.py +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/tests/test_refinement_session.py +0 -0
- {diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/tests/test_runmacro.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: diffpy.apps
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.0rc2
|
|
4
4
|
Summary: User applications to help with tasks using diffpy packages
|
|
5
|
-
Author-email: Yuchen Xiao <
|
|
6
|
-
Maintainer-email:
|
|
5
|
+
Author-email: Yuchen Xiao <xiaoyuch@msu.edu>, Simon Billinge <sbillinge@ucsb.edu>
|
|
6
|
+
Maintainer-email: Simon Billinge <sbillinge@ucsb.edu>
|
|
7
7
|
License-Expression: BSD-3-Clause
|
|
8
8
|
Project-URL: Homepage, https://github.com/diffpy/diffpy.apps/
|
|
9
9
|
Project-URL: Issues, https://github.com/diffpy/diffpy.apps/issues/
|
|
@@ -16,12 +16,12 @@ Classifier: Operating System :: MacOS :: MacOS X
|
|
|
16
16
|
Classifier: Operating System :: Microsoft :: Windows
|
|
17
17
|
Classifier: Operating System :: POSIX
|
|
18
18
|
Classifier: Operating System :: Unix
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
21
20
|
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
22
22
|
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
23
23
|
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
24
|
-
Requires-Python: <3.
|
|
24
|
+
Requires-Python: <3.15,>=3.12
|
|
25
25
|
Description-Content-Type: text/x-rst
|
|
26
26
|
License-File: LICENSE.rst
|
|
27
27
|
License-File: AUTHORS.rst
|
|
@@ -6,17 +6,16 @@ build-backend = "setuptools.build_meta"
|
|
|
6
6
|
name = "diffpy.apps"
|
|
7
7
|
dynamic=['version', 'dependencies']
|
|
8
8
|
authors = [
|
|
9
|
-
{name='Yuchen Xiao', email='
|
|
9
|
+
{name='Yuchen Xiao', email='xiaoyuch@msu.edu'},
|
|
10
10
|
{name='Simon Billinge', email='sbillinge@ucsb.edu'},
|
|
11
11
|
]
|
|
12
12
|
maintainers = [
|
|
13
|
-
{name='Yuchen Xiao', email='yx2924@columbia.edu'},
|
|
14
13
|
{name='Simon Billinge', email='sbillinge@ucsb.edu'},
|
|
15
14
|
]
|
|
16
15
|
description = "User applications to help with tasks using diffpy packages"
|
|
17
16
|
keywords = ['diffraction', 'PDF', 'X-ray', 'neutron']
|
|
18
17
|
readme = "README.rst"
|
|
19
|
-
requires-python = ">=3.
|
|
18
|
+
requires-python = ">=3.12, <3.15"
|
|
20
19
|
classifiers = [
|
|
21
20
|
'Development Status :: 5 - Production/Stable',
|
|
22
21
|
'Environment :: Console',
|
|
@@ -26,9 +25,9 @@ classifiers = [
|
|
|
26
25
|
'Operating System :: Microsoft :: Windows',
|
|
27
26
|
'Operating System :: POSIX',
|
|
28
27
|
'Operating System :: Unix',
|
|
29
|
-
'Programming Language :: Python :: 3.11',
|
|
30
28
|
'Programming Language :: Python :: 3.12',
|
|
31
29
|
'Programming Language :: Python :: 3.13',
|
|
30
|
+
'Programming Language :: Python :: 3.14',
|
|
32
31
|
'Topic :: Scientific/Engineering :: Physics',
|
|
33
32
|
'Topic :: Scientific/Engineering :: Chemistry',
|
|
34
33
|
]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
##############################################################################
|
|
3
|
+
#
|
|
4
|
+
# (c) 2026 diffpy.apps contributors.
|
|
5
|
+
# All rights reserved.
|
|
6
|
+
#
|
|
7
|
+
# File coded by: Billinge Group members and community contributors.
|
|
8
|
+
#
|
|
9
|
+
# See GitHub contributions for a more detailed list of contributors.
|
|
10
|
+
# https://github.com/diffpy/diffpy.apps/graphs/contributors
|
|
11
|
+
#
|
|
12
|
+
# See LICENSE.rst for license information.
|
|
13
|
+
#
|
|
14
|
+
##############################################################################
|
|
@@ -2,10 +2,10 @@ import shutil
|
|
|
2
2
|
import socket
|
|
3
3
|
import subprocess
|
|
4
4
|
import tempfile
|
|
5
|
+
import warnings
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
|
|
7
8
|
REPO_URL = "https://github.com/diffpy/cmi-agent-skills"
|
|
8
|
-
DIR_NAME = "cmi-skill"
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def ensure_setup():
|
|
@@ -35,21 +35,31 @@ def agentify(args):
|
|
|
35
35
|
elif agent == "codex":
|
|
36
36
|
skills_dir = ".codex/skills"
|
|
37
37
|
if system_flag:
|
|
38
|
-
|
|
38
|
+
dest_dir = Path().home() / skills_dir
|
|
39
39
|
else:
|
|
40
|
-
|
|
41
|
-
if destination.exists() and not args.update:
|
|
42
|
-
raise FileExistsError(
|
|
43
|
-
f"Agentic skill {DIR_NAME} already exists at {destination}. "
|
|
44
|
-
"To overwrite, pass '--update' flag to update the skill"
|
|
45
|
-
)
|
|
40
|
+
dest_dir = Path().cwd() / skills_dir
|
|
46
41
|
with tempfile.TemporaryDirectory() as tmp:
|
|
47
42
|
tmp_path = Path(tmp)
|
|
48
43
|
subprocess.run(
|
|
49
44
|
["git", "clone", REPO_URL, str(tmp_path)],
|
|
50
45
|
check=True,
|
|
51
46
|
)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
47
|
+
for item in tmp_path.iterdir():
|
|
48
|
+
if item.is_dir():
|
|
49
|
+
destination = dest_dir / item.name
|
|
50
|
+
if destination.exists():
|
|
51
|
+
if args.update:
|
|
52
|
+
shutil.rmtree(destination)
|
|
53
|
+
shutil.copytree(item, destination, dirs_exist_ok=True)
|
|
54
|
+
print(f"Updated existing skill at {destination}")
|
|
55
|
+
else:
|
|
56
|
+
warnings.warn(
|
|
57
|
+
f"Skill at {destination} already exists. "
|
|
58
|
+
"Use '--update' flag to overwrite."
|
|
59
|
+
)
|
|
60
|
+
continue
|
|
61
|
+
else:
|
|
62
|
+
shutil.copytree(item, destination, dirs_exist_ok=True)
|
|
63
|
+
print(
|
|
64
|
+
f"Skill {item.name} has been deployed to {destination}"
|
|
65
|
+
)
|
|
@@ -12,8 +12,8 @@ from diffpy.srfit.fitbase import (
|
|
|
12
12
|
Profile,
|
|
13
13
|
)
|
|
14
14
|
from diffpy.srfit.pdf import PDFGenerator, PDFParser
|
|
15
|
-
from diffpy.srfit.structure import
|
|
16
|
-
from diffpy.structure.parsers import
|
|
15
|
+
from diffpy.srfit.structure import constrain_as_space_group
|
|
16
|
+
from diffpy.structure.parsers import get_parser
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class PDFAdapter:
|
|
@@ -147,7 +147,7 @@ class PDFAdapter:
|
|
|
147
147
|
run_parallel = False
|
|
148
148
|
for i, structure_path in enumerate(structure_paths):
|
|
149
149
|
name = names[i] if names and i < len(names) else f"G{i+1}"
|
|
150
|
-
stru_parser =
|
|
150
|
+
stru_parser = get_parser("cif")
|
|
151
151
|
structure = stru_parser.parse(Path(structure_path).read_text())
|
|
152
152
|
sg = getattr(stru_parser, "spacegroup", None)
|
|
153
153
|
spacegroup = sg.short_name if sg is not None else "P1"
|
|
@@ -176,7 +176,7 @@ class PDFAdapter:
|
|
|
176
176
|
----------
|
|
177
177
|
equation : list of str, optional
|
|
178
178
|
The list of a single equation passed to
|
|
179
|
-
FitContribution.
|
|
179
|
+
FitContribution.set_equation
|
|
180
180
|
|
|
181
181
|
Returns
|
|
182
182
|
-------
|
|
@@ -202,7 +202,6 @@ class PDFAdapter:
|
|
|
202
202
|
delta1 and delta2 variables, and structure parameters
|
|
203
203
|
constrained by the space group.
|
|
204
204
|
"""
|
|
205
|
-
|
|
206
205
|
recipe = FitRecipe()
|
|
207
206
|
recipe.add_contribution(self.contribution)
|
|
208
207
|
qdamp = recipe.create_new_variable("qdamp", fixed=False, value=0.04)
|
|
@@ -221,7 +220,9 @@ class PDFAdapter:
|
|
|
221
220
|
recipe.add_constraint(pdfgenerator.qdamp, qdamp)
|
|
222
221
|
recipe.add_constraint(pdfgenerator.qbroad, qbroad)
|
|
223
222
|
stru_parset = pdfgenerator.phase
|
|
224
|
-
spacegroupparams =
|
|
223
|
+
spacegroupparams = constrain_as_space_group(
|
|
224
|
+
stru_parset, spacegroup
|
|
225
|
+
)
|
|
225
226
|
for par in spacegroupparams.xyzpars:
|
|
226
227
|
recipe.add_variable(
|
|
227
228
|
par, name=f"{pdfgenerator.name}_{par.name}", fixed=False
|
{diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/src/diffpy/apps/refinebase/parametric_model.py
RENAMED
|
@@ -199,8 +199,7 @@ class ParametricModelEquation(ParametricModel):
|
|
|
199
199
|
|
|
200
200
|
class ParametricModelFunction(ParametricModel):
|
|
201
201
|
def __init__(self, name, function, argnames=None):
|
|
202
|
-
"""
|
|
203
|
-
Initialize a ParametricModelFunction instance.
|
|
202
|
+
"""Initialize a ParametricModelFunction instance.
|
|
204
203
|
|
|
205
204
|
function can be either a callable or a string representing
|
|
206
205
|
the pre-defined function.
|
|
@@ -254,8 +253,7 @@ class ParametricModelPDF(ParametricModel):
|
|
|
254
253
|
finite=False,
|
|
255
254
|
run_parallel=True,
|
|
256
255
|
):
|
|
257
|
-
"""
|
|
258
|
-
Create a ParametricModelPDF instance from a structure object.
|
|
256
|
+
"""Create a ParametricModelPDF instance from a structure object.
|
|
259
257
|
|
|
260
258
|
structure can be a raw diffpy.structure/pyobjcryst structure, or
|
|
261
259
|
an existing DiffpyStructureParSet/ObjCrystCrystalParSet phase
|
|
@@ -615,10 +613,11 @@ def create_pdf_model_from_code(
|
|
|
615
613
|
finite=False,
|
|
616
614
|
run_parallel=True,
|
|
617
615
|
):
|
|
618
|
-
"""Create a ParametricModelPDF by executing code that builds a
|
|
616
|
+
"""Create a ParametricModelPDF by executing code that builds a
|
|
617
|
+
structure.
|
|
619
618
|
|
|
620
|
-
The code must assign the structure/crystal object to a variable
|
|
621
|
-
structure_name (default "structure") in its local namespace.
|
|
619
|
+
The code must assign the structure/crystal object to a variable
|
|
620
|
+
named structure_name (default "structure") in its local namespace.
|
|
622
621
|
"""
|
|
623
622
|
local_namespace = {}
|
|
624
623
|
exec(code, global_namespace, local_namespace)
|
|
@@ -645,8 +644,8 @@ def create_pdf_model_from_code(
|
|
|
645
644
|
if hasattr(structure, "GetCrystal")
|
|
646
645
|
else structure
|
|
647
646
|
)
|
|
648
|
-
if hasattr(crystal, "
|
|
649
|
-
spacegroup_symbol = crystal.
|
|
647
|
+
if hasattr(crystal, "get_space_group"):
|
|
648
|
+
spacegroup_symbol = crystal.get_space_group().get_name()
|
|
650
649
|
else:
|
|
651
650
|
logging.warning(
|
|
652
651
|
"Could not determine a space group for the structure named "
|
{diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/src/diffpy/apps/refinebase/refinement_server.py
RENAMED
|
@@ -102,7 +102,8 @@ async def set_profile_calculation_range(
|
|
|
102
102
|
xmax: Annotated[float, "End of the calculation range"] = None,
|
|
103
103
|
dx: Annotated[float, "Step size for the calculation range"] = None,
|
|
104
104
|
) -> str:
|
|
105
|
-
"""Set the calculation range for a profile in the refinement
|
|
105
|
+
"""Set the calculation range for a profile in the refinement
|
|
106
|
+
session."""
|
|
106
107
|
session.set_profile_calculation_range(
|
|
107
108
|
profile_name, xmin=xmin, xmax=xmax, dx=dx
|
|
108
109
|
)
|
|
@@ -191,8 +192,8 @@ async def add_pdf_model(
|
|
|
191
192
|
bool, "Whether to run the PDF model in parallel"
|
|
192
193
|
] = True,
|
|
193
194
|
) -> str:
|
|
194
|
-
"""
|
|
195
|
-
|
|
195
|
+
"""Add a structure-file-based parametric model to the refinement
|
|
196
|
+
session.
|
|
196
197
|
|
|
197
198
|
Parameters
|
|
198
199
|
----------
|
|
@@ -247,8 +248,7 @@ async def add_function_model(
|
|
|
247
248
|
list[str] | None, "Argument names for the function"
|
|
248
249
|
] = None,
|
|
249
250
|
) -> str:
|
|
250
|
-
"""
|
|
251
|
-
Add a function model to the refinement session.
|
|
251
|
+
"""Add a function model to the refinement session.
|
|
252
252
|
|
|
253
253
|
function can be either a callable or a string representing
|
|
254
254
|
the pre-defined function.
|
|
@@ -282,7 +282,8 @@ async def set_model_equation(
|
|
|
282
282
|
model_name: Annotated[str, "Name of the parametric model"],
|
|
283
283
|
equation: Annotated[str, "New equation for the parametric model"],
|
|
284
284
|
) -> str:
|
|
285
|
-
"""Set the equation for an existing parametric model in the
|
|
285
|
+
"""Set the equation for an existing parametric model in the
|
|
286
|
+
session."""
|
|
286
287
|
session.set_model_equation(model_name=model_name, equation=equation)
|
|
287
288
|
return f"Equation for model {model_name} set successfully."
|
|
288
289
|
|
|
@@ -339,7 +340,8 @@ async def set_model_profile(
|
|
|
339
340
|
model_name: Annotated[str, "Name of the parametric model"],
|
|
340
341
|
profile_name: Annotated[str, "Name of the profile to set on the model"],
|
|
341
342
|
) -> str:
|
|
342
|
-
"""Set the profile for a parametric model in the refinement
|
|
343
|
+
"""Set the profile for a parametric model in the refinement
|
|
344
|
+
session."""
|
|
343
345
|
session.set_model_profile(model_name, profile_name)
|
|
344
346
|
return f"Profile {profile_name} set for model {model_name} successfully."
|
|
345
347
|
|
|
@@ -365,7 +367,8 @@ async def get_profile_data(
|
|
|
365
367
|
profile_name: Annotated[str, "Name of the profile to retrieve"],
|
|
366
368
|
data_path: Annotated[str, "Path to the data to retrieve"],
|
|
367
369
|
) -> str:
|
|
368
|
-
"""Get the details of a specific profile in the refinement
|
|
370
|
+
"""Get the details of a specific profile in the refinement
|
|
371
|
+
session."""
|
|
369
372
|
profile = session.profiles_dict[profile_name]
|
|
370
373
|
data = {"xobs": profile.xobs.tolist(), "yobs": profile.yobs.tolist()}
|
|
371
374
|
with open(data_path, "w") as f:
|
|
@@ -395,8 +398,8 @@ async def constrain_pdf_model_space_group_symmetry(
|
|
|
395
398
|
) -> str:
|
|
396
399
|
"""Constrain a parametric model to a specific space group symmetry.
|
|
397
400
|
|
|
398
|
-
If no space group is provided, the model will be constrained to
|
|
399
|
-
|
|
401
|
+
If no space group is provided, the model will be constrained to its
|
|
402
|
+
current space group parsed from its structure.
|
|
400
403
|
"""
|
|
401
404
|
session.constrain_pdf_model_space_group_symmetry(model_name, space_group)
|
|
402
405
|
return (
|
|
@@ -428,9 +431,8 @@ async def combine_models(
|
|
|
428
431
|
list[str], "Names of the child parametric models"
|
|
429
432
|
],
|
|
430
433
|
) -> str:
|
|
431
|
-
"""
|
|
432
|
-
|
|
433
|
-
"""
|
|
434
|
+
"""Combine two parametric models by registering the child to the
|
|
435
|
+
parent model."""
|
|
434
436
|
session.combine_models(parent_model_name, child_model_names)
|
|
435
437
|
return (
|
|
436
438
|
f"Models {parent_model_name} and "
|
|
@@ -445,9 +447,7 @@ async def set_variables_value(
|
|
|
445
447
|
dict, "Mapping of variable names to the values to set them to"
|
|
446
448
|
],
|
|
447
449
|
) -> str:
|
|
448
|
-
"""
|
|
449
|
-
Set the value of a specific variable in a parametric model.
|
|
450
|
-
"""
|
|
450
|
+
"""Set the value of a specific variable in a parametric model."""
|
|
451
451
|
session.set_variables_value(name_value_dict)
|
|
452
452
|
|
|
453
453
|
return f"Variables '{name_value_dict}' are set."
|
|
@@ -458,9 +458,7 @@ async def set_variables_value(
|
|
|
458
458
|
async def get_variable(
|
|
459
459
|
variable_name: Annotated[str, "Name of the variable"],
|
|
460
460
|
) -> str:
|
|
461
|
-
"""
|
|
462
|
-
Get the value of a specific variable in a parametric model.
|
|
463
|
-
"""
|
|
461
|
+
"""Get the value of a specific variable in a parametric model."""
|
|
464
462
|
variable = session.get_variable(variable_name)
|
|
465
463
|
return f"Variable '{variable_name}': {variable['value']}"
|
|
466
464
|
|
|
@@ -473,9 +471,7 @@ async def list_model_parameters(
|
|
|
473
471
|
bool, "Whether to list only independent parameters"
|
|
474
472
|
] = True,
|
|
475
473
|
) -> str:
|
|
476
|
-
"""
|
|
477
|
-
List all parameters of a specific parametric model.
|
|
478
|
-
"""
|
|
474
|
+
"""List all parameters of a specific parametric model."""
|
|
479
475
|
if model_name not in session.models_dict:
|
|
480
476
|
raise ValueError(f"Model with ID {model_name} does not exist.")
|
|
481
477
|
|
|
@@ -495,9 +491,7 @@ async def list_model_parameters(
|
|
|
495
491
|
@mcp.tool()
|
|
496
492
|
@tool_errors
|
|
497
493
|
async def clear() -> str:
|
|
498
|
-
"""
|
|
499
|
-
Clear the current refinement session.
|
|
500
|
-
"""
|
|
494
|
+
"""Clear the current refinement session."""
|
|
501
495
|
session.clear()
|
|
502
496
|
return "Refinement session cleared successfully."
|
|
503
497
|
|
|
@@ -507,9 +501,7 @@ async def clear() -> str:
|
|
|
507
501
|
async def list_recipe_parameters(
|
|
508
502
|
recipe_name: Annotated[str, "Name of the recipe"],
|
|
509
503
|
) -> str:
|
|
510
|
-
"""
|
|
511
|
-
List all parameters of a specific recipe.
|
|
512
|
-
"""
|
|
504
|
+
"""List all parameters of a specific recipe."""
|
|
513
505
|
if recipe_name not in session.recipes_dict:
|
|
514
506
|
raise ValueError(f"Recipe with ID {recipe_name} does not exist.")
|
|
515
507
|
|
|
@@ -552,8 +544,8 @@ async def solve(
|
|
|
552
544
|
bool, "Whether to also include sgpars from the models automatically"
|
|
553
545
|
] = False,
|
|
554
546
|
) -> str:
|
|
555
|
-
"""
|
|
556
|
-
|
|
547
|
+
"""Initiate a refinement using the specified profiles, models, and
|
|
548
|
+
variables.
|
|
557
549
|
|
|
558
550
|
Parameters
|
|
559
551
|
----------
|
{diffpy_apps-0.2.0rc0 → diffpy_apps-0.2.0rc2}/src/diffpy/apps/refinebase/refinement_session.py
RENAMED
|
@@ -67,7 +67,7 @@ class RefinementSession:
|
|
|
67
67
|
if profile_name is None:
|
|
68
68
|
profile_name = str(uuid.uuid4())
|
|
69
69
|
profile = Profile()
|
|
70
|
-
profile.
|
|
70
|
+
profile.set_observed_profile(xobs=xarray, yobs=yarray, dyobs=dy)
|
|
71
71
|
profile.xpar.name = xname
|
|
72
72
|
profile._xname = xname
|
|
73
73
|
profile.ypar.name = yname
|
|
@@ -531,7 +531,7 @@ class RefinementSession:
|
|
|
531
531
|
par = self.get_variable(eq_or_var_name)["obj"]
|
|
532
532
|
par.bound_range(lb, ub)
|
|
533
533
|
recipe.free("all")
|
|
534
|
-
leastsq(recipe.residual, recipe.
|
|
534
|
+
leastsq(recipe.residual, recipe.get_values())
|
|
535
535
|
# NOTE: non-scalar value will raise error in `get_results_string`
|
|
536
536
|
try:
|
|
537
537
|
result_string = FitResults(recipe).get_results_string()
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: diffpy.apps
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.0rc2
|
|
4
4
|
Summary: User applications to help with tasks using diffpy packages
|
|
5
|
-
Author-email: Yuchen Xiao <
|
|
6
|
-
Maintainer-email:
|
|
5
|
+
Author-email: Yuchen Xiao <xiaoyuch@msu.edu>, Simon Billinge <sbillinge@ucsb.edu>
|
|
6
|
+
Maintainer-email: Simon Billinge <sbillinge@ucsb.edu>
|
|
7
7
|
License-Expression: BSD-3-Clause
|
|
8
8
|
Project-URL: Homepage, https://github.com/diffpy/diffpy.apps/
|
|
9
9
|
Project-URL: Issues, https://github.com/diffpy/diffpy.apps/issues/
|
|
@@ -16,12 +16,12 @@ Classifier: Operating System :: MacOS :: MacOS X
|
|
|
16
16
|
Classifier: Operating System :: Microsoft :: Windows
|
|
17
17
|
Classifier: Operating System :: POSIX
|
|
18
18
|
Classifier: Operating System :: Unix
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
21
20
|
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
22
22
|
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
23
23
|
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
24
|
-
Requires-Python: <3.
|
|
24
|
+
Requires-Python: <3.15,>=3.12
|
|
25
25
|
Description-Content-Type: text/x-rst
|
|
26
26
|
License-File: LICENSE.rst
|
|
27
27
|
License-File: AUTHORS.rst
|
|
@@ -39,5 +39,5 @@ def sine_profile():
|
|
|
39
39
|
xobs = numpy.linspace(-numpy.pi, numpy.pi, 100)
|
|
40
40
|
yobs = numpy.sin(xobs) + 1e-3 * numpy.random.normal(size=xobs.shape)
|
|
41
41
|
sine_profile = Profile()
|
|
42
|
-
sine_profile.
|
|
42
|
+
sine_profile.set_observed_profile(xobs, yobs)
|
|
43
43
|
return sine_profile
|
|
@@ -10,8 +10,8 @@ from diffpy.srfit.fitbase import (
|
|
|
10
10
|
Profile,
|
|
11
11
|
)
|
|
12
12
|
from diffpy.srfit.pdf import DebyePDFGenerator, PDFGenerator, PDFParser
|
|
13
|
-
from diffpy.srfit.structure import
|
|
14
|
-
from diffpy.structure.parsers import
|
|
13
|
+
from diffpy.srfit.structure import constrain_as_space_group
|
|
14
|
+
from diffpy.structure.parsers import get_parser
|
|
15
15
|
|
|
16
16
|
_DATA_DIR = Path(__file__).parent / "data"
|
|
17
17
|
|
|
@@ -49,21 +49,21 @@ def run_ni_example():
|
|
|
49
49
|
QBROAD_I = 0.02
|
|
50
50
|
RUN_PARALLEL = True
|
|
51
51
|
|
|
52
|
-
p_cif =
|
|
53
|
-
stru1 = p_cif.
|
|
52
|
+
p_cif = get_parser("cif")
|
|
53
|
+
stru1 = p_cif.parse_file(structure_path)
|
|
54
54
|
sg = p_cif.spacegroup.short_name
|
|
55
55
|
profile = Profile()
|
|
56
56
|
parser = PDFParser()
|
|
57
|
-
parser.
|
|
58
|
-
profile.
|
|
59
|
-
profile.
|
|
57
|
+
parser.parse_file(profile_path)
|
|
58
|
+
profile.load_parsed_data(parser)
|
|
59
|
+
profile.set_calculation_range(xmin=PDF_RMIN, xmax=PDF_RMAX, dx=PDF_RSTEP)
|
|
60
60
|
generator_crystal1 = PDFGenerator("G1")
|
|
61
61
|
generator_crystal1.setStructure(stru1, periodic=True)
|
|
62
62
|
generator_crystal1.setQmax(QMAX)
|
|
63
63
|
generator_crystal1.setQmin(QMIN)
|
|
64
64
|
generator_crystal1.delta2.value = DELTA2_I
|
|
65
65
|
contribution = FitContribution("crystal")
|
|
66
|
-
contribution.
|
|
66
|
+
contribution.add_profile_generator(generator_crystal1)
|
|
67
67
|
if RUN_PARALLEL:
|
|
68
68
|
try:
|
|
69
69
|
import multiprocessing
|
|
@@ -82,28 +82,28 @@ def run_ni_example():
|
|
|
82
82
|
"\nYou don't appear to have the necessary packages for "
|
|
83
83
|
"parallelization"
|
|
84
84
|
)
|
|
85
|
-
contribution.
|
|
86
|
-
contribution.
|
|
85
|
+
contribution.set_profile(profile, xname="r")
|
|
86
|
+
contribution.set_equation("s0*G1")
|
|
87
87
|
recipe = FitRecipe()
|
|
88
|
-
recipe.
|
|
88
|
+
recipe.add_contribution(contribution)
|
|
89
89
|
recipe.crystal.G1.qdamp.value = QDAMP_I
|
|
90
90
|
recipe.crystal.G1.qbroad.value = QBROAD_I
|
|
91
91
|
recipe.crystal.G1.setQmax(QMAX)
|
|
92
92
|
recipe.crystal.G1.setQmin(QMIN)
|
|
93
|
-
recipe.
|
|
94
|
-
spacegroupparams =
|
|
93
|
+
recipe.add_variable(contribution.s0, SCALE_I, name="s0")
|
|
94
|
+
spacegroupparams = constrain_as_space_group(generator_crystal1.phase, sg)
|
|
95
95
|
for par in spacegroupparams.latpars:
|
|
96
|
-
recipe.
|
|
96
|
+
recipe.add_variable(par, value=CUBICLAT_I, fixed=False, name="G1_a")
|
|
97
97
|
for par in spacegroupparams.adppars:
|
|
98
|
-
recipe.
|
|
99
|
-
recipe.
|
|
100
|
-
recipe.
|
|
98
|
+
recipe.add_variable(par, value=UISO_I, fixed=False, name="G1_Uiso_0")
|
|
99
|
+
recipe.add_variable(generator_crystal1.delta2, name="G1_delta2")
|
|
100
|
+
recipe.add_variable(
|
|
101
101
|
generator_crystal1.qdamp,
|
|
102
102
|
fixed=False,
|
|
103
103
|
name="qdamp",
|
|
104
104
|
value=QDAMP_I,
|
|
105
105
|
)
|
|
106
|
-
recipe.
|
|
106
|
+
recipe.add_variable(
|
|
107
107
|
generator_crystal1.qbroad,
|
|
108
108
|
fixed=False,
|
|
109
109
|
name="qbroad",
|
|
@@ -28,7 +28,7 @@ pytestmark = pytest.mark.skipif(
|
|
|
28
28
|
update=False,
|
|
29
29
|
),
|
|
30
30
|
"cwd",
|
|
31
|
-
".claude/skills/
|
|
31
|
+
".claude/skills/diffpy-playbook",
|
|
32
32
|
),
|
|
33
33
|
# C2: diffpy.apps agentify --system
|
|
34
34
|
# Deploys system claude skill.
|
|
@@ -40,7 +40,7 @@ pytestmark = pytest.mark.skipif(
|
|
|
40
40
|
update=False,
|
|
41
41
|
),
|
|
42
42
|
"home",
|
|
43
|
-
".claude/skills/
|
|
43
|
+
".claude/skills/diffpy-playbook",
|
|
44
44
|
),
|
|
45
45
|
# C3: diffpy.apps agentify --agent codex
|
|
46
46
|
# Deploys workspace codex skill.
|
|
@@ -52,7 +52,7 @@ pytestmark = pytest.mark.skipif(
|
|
|
52
52
|
update=False,
|
|
53
53
|
),
|
|
54
54
|
"cwd",
|
|
55
|
-
".codex/skills/
|
|
55
|
+
".codex/skills/diffpy-playbook",
|
|
56
56
|
),
|
|
57
57
|
# C4: diffpy.apps agentify --agent codex --system
|
|
58
58
|
# Deploys system codex skill.
|
|
@@ -64,7 +64,7 @@ pytestmark = pytest.mark.skipif(
|
|
|
64
64
|
update=False,
|
|
65
65
|
),
|
|
66
66
|
"home",
|
|
67
|
-
".codex/skills/
|
|
67
|
+
".codex/skills/diffpy-playbook",
|
|
68
68
|
),
|
|
69
69
|
],
|
|
70
70
|
)
|
|
@@ -94,14 +94,17 @@ def test_agentify_update():
|
|
|
94
94
|
update=False,
|
|
95
95
|
)
|
|
96
96
|
agentify(args)
|
|
97
|
-
skill_path =
|
|
97
|
+
skill_path = (
|
|
98
|
+
Path(tmp) / "cwd" / ".claude" / "skills" / "diffpy-playbook"
|
|
99
|
+
)
|
|
98
100
|
assert skill_path.exists()
|
|
99
101
|
args.update = True
|
|
100
102
|
agentify(args)
|
|
101
103
|
pytest.raises(
|
|
102
104
|
FileExistsError,
|
|
103
105
|
match=re.escape(
|
|
104
|
-
|
|
106
|
+
"Agentic skill diffpy-playbook already exists at "
|
|
107
|
+
f"{skill_path}. "
|
|
105
108
|
"To overwrite, pass '--update' flag to update the skill"
|
|
106
109
|
),
|
|
107
110
|
)
|
|
@@ -37,7 +37,9 @@ def test_pdfadapter():
|
|
|
37
37
|
adapter.initialize_structures([str(structure_path)])
|
|
38
38
|
adapter.initialize_contribution(equation=["s0*G1"])
|
|
39
39
|
adapter.initialize_recipe()
|
|
40
|
-
adapter.recipe.
|
|
40
|
+
adapter.recipe.add_variable(
|
|
41
|
+
list(adapter.recipe._contributions.values())[0].s0
|
|
42
|
+
)
|
|
41
43
|
adapter.set_initial_variable_values(initial_pv_dict)
|
|
42
44
|
adapter.recipe.fix("all")
|
|
43
45
|
for var in variables_to_refine:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{diffpy_apps-0.2.0rc0/src/diffpy → diffpy_apps-0.2.0rc2/src/diffpy/apps/refinebase}/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|