Repository navigation
Expand file tree
/
Copy pathtest_parametric_model.py
More file actions
145 lines (131 loc) · 4.9 KB
/
Copy pathtest_parametric_model.py
File metadata and controls
145 lines (131 loc) · 4.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
from pathlib import Path
import numpy
import pytest
from diffpy.apps.parametric_refinement.parametric_model import (
ParametricModelEquation,
ParametricModelFunction,
create_pdf_model_from_file,
)
from diffpy.srfit.fitbase import (
Profile,
)
from diffpy.srfit.pdf import PDFParser
_DATA_DIR = Path(__file__).parent / "data"
def test_parametric_model_graph():
# C1: Create a nested parametric model
# Expect the graph to be constructed correctly
model = ParametricModelEquation("main", "A*sin(u)")
submodel = ParametricModelEquation("sub", "a*x")
model.register_submodel(symbol="u", submodel=submodel)
expected_parameters = ["main.A", "main.sub.a", "main.sub.x"]
actual_parameters = list(model.parameters.keys())
assert set(expected_parameters) == set(actual_parameters)
expected_edges = [
("main", "main.A"),
("main", "main.sub"),
("main.sub", "main.sub.a"),
("main.sub", "main.sub.x"),
]
actual_edges = list(model._graph.edges)
assert set(expected_edges) == set(actual_edges)
def test_parametric_model_parameter_access(nested_sine_model):
# C1: Create a nested sine parametric model
# Expect to models to share the same parameter obj
model, submodel = nested_sine_model
assert model.parameters["main.sub.a"] is submodel.parameters["sub.a"]
@pytest.mark.parametrize(
"A, a, x, expected",
[
(1.0, 1.0, numpy.pi / 2, 1.0),
(2.0, 2.0, numpy.pi / 4, 2.0),
(1.0, 1.0, numpy.pi, 0.0),
],
)
def test_parametric_model_evaluation(nested_sine_model, A, a, x, expected):
# C1: Create a nested sine parametric model
# Expect the model to evaluate correctly
model, submodel = nested_sine_model
model.parameters["main.A"].value = A
submodel.parameters["sub.a"].value = a
submodel.parameters["sub.x"].value = x
actual = model.evaluate()
assert numpy.isclose(actual, expected, rtol=1e-6)
def test_parametric_pdf_model_parameters():
# C1: Create a ParametricModelPDF for Ni
# Expect the model to be initialized correctly with all parameters
profile_path = str(_DATA_DIR / "Ni.gr")
profile = Profile()
parser = PDFParser()
parser.parse_file(profile_path)
profile.load_parsed_data(parser)
profile.set_calculation_range(xmax=20)
pdf_model = create_pdf_model_from_file(
"ni",
structure_file_path=str(_DATA_DIR / "Ni.cif"),
finite=False,
)
parameter_names = [
"ni.phase.lattice.a",
"ni.phase.Ni0.Uiso",
"ni.delta1",
"ni.delta2",
"ni.qbroad",
"ni.scale",
"ni.qdamp",
"ni.phase.Ni0.occ",
"ni.phase.Ni1.occ",
"ni.phase.Ni2.occ",
"ni.phase.Ni3.occ",
]
assert set(parameter_names).issubset(set(pdf_model.parameters.keys()))
pdf_model.constrain_symmetry("Fm-3m")
assert set(parameter_names) == set(pdf_model.independent_parameters.keys())
def test_parametric_function_model():
# C1: Create a ParametricModelFunction with a simple function
# Expect the model to be initialized correctly with the function
# registered
def sine_func(x):
return numpy.sin(x)
xobs = numpy.arange(100)
expected_y = sine_func(xobs)
profile = Profile()
profile.set_observed_profile(xobs, expected_y)
func_model = ParametricModelFunction("func_model", function=sine_func)
func_model.set_profile(profile)
actual_y = func_model.evaluate()
assert numpy.allclose(actual_y, expected_y, rtol=1e-6)
expected_pnames = ["func_model.x"]
assert list(expected_pnames) == list(func_model.parameters.keys())
# C2: Create a PrametricModelFunction with a characteristic function
# Expect the model to evaluate correctly with the characteristic function
spherical_fun = ParametricModelFunction(
"spherical_func_model", function="spherical_particle"
)
expected_pnames = [
"spherical_func_model.r",
"spherical_func_model.particle_diameter",
]
actual_pnames = list(spherical_fun.parameters.keys())
assert set(expected_pnames) == set(actual_pnames)
xobs = numpy.arange(100)
expected_y = sine_func(xobs)
profile = Profile()
profile.set_observed_profile(xobs, expected_y)
spherical_fun.set_profile(profile, xname="r")
spherical_fun.parameters[
"spherical_func_model.particle_diameter"
].value = 10
r = xobs
particle_diameter = 10
# copied from diffpy.srfit.pdf.characteristic_functions.spherical_particle
# start
characteristic_function = numpy.zeros(numpy.shape(r), dtype=float)
scaled_r = numpy.array(r, dtype=float) / particle_diameter
inside = scaled_r < 1.0
scaled_r_inside = scaled_r[inside]
characteristic_function[inside] = (
1.0 - 1.5 * scaled_r_inside + 0.5 * scaled_r_inside**3
)
# end
expected_y = characteristic_function
assert numpy.allclose(spherical_fun.evaluate(), expected_y, rtol=1e-6)