Skip to content

Commit a391b7a

Browse files
authored
Merge pull request #165 from cadenmyers13/res-dict
deprecate: Deprecate `resultsDictionary`
2 parents 6de334f + fc672df commit a391b7a

File tree

4 files changed

+161
-2
lines changed

4 files changed

+161
-2
lines changed

news/res-dict.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
**Added:**
2+
3+
* Added ``FitResults.get_results_dictionary`` in replace of ``resultsDictionary``.
4+
5+
**Changed:**
6+
7+
* <news item>
8+
9+
**Deprecated:**
10+
11+
* Deprecated ``resultsDictionary`` for removal in 4.0.0.
12+
13+
**Removed:**
14+
15+
* <news item>
16+
17+
**Fixed:**
18+
19+
* <news item>
20+
21+
**Security:**
22+
23+
* <news item>

src/diffpy/srfit/fitbase/fitresults.py

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@
5757
removal_version,
5858
)
5959

60+
resultsDictionary_dep_msg = build_deprecation_message(
61+
"diffpy.srfit.fitbase",
62+
"resultsDictionary",
63+
"get_results_dictionary",
64+
removal_version,
65+
new_base="diffpy.srfit.fitbase.FitResults",
66+
)
67+
6068

6169
class FitResults(object):
6270
"""Class for processing, presenting and storing results of a fit.
@@ -619,6 +627,31 @@ def saveResults(self, filename, header="", footer="", update=False):
619627
self.save_results(filename, header, footer, update)
620628
return
621629

630+
def get_results_dictionary(self):
631+
"""Get a dictionary of results, with variable names and values, and
632+
overall metrics.
633+
634+
Returns
635+
-------
636+
results_dict : dict
637+
A dictionary containing the variable names and values, and overall
638+
metrics, from the FitResults.
639+
"""
640+
parameter_names = self.varnames
641+
parameter_values = self.varvals
642+
results_dict = dict(zip(parameter_names, parameter_values))
643+
results_dict.update(
644+
{
645+
"Residual": self.residual,
646+
"Contributions": self.residual - self.penalty,
647+
"Restraints": self.penalty,
648+
"Chi2": self.chi2,
649+
"Reduced Chi2": self.rchi2,
650+
"Rw": self.rw,
651+
}
652+
)
653+
return results_dict
654+
622655

623656
# End class FitResults
624657

@@ -750,8 +783,15 @@ def _calculate_metrics(self):
750783
# End class ContributionResults
751784

752785

786+
@deprecated(resultsDictionary_dep_msg)
753787
def resultsDictionary(results):
754-
"""Get dictionary of results from file.
788+
"""**This function has been deprecated and will be** **removed in version
789+
4.0.0.**
790+
791+
**Please use**
792+
**diffpy.srfit.fitbase.FitResults.get_results_dictionary instead.**
793+
794+
Get dictionary of results from file.
755795
756796
This reads the results from file and stores them in a dictionary to be
757797
returned to the caller. The dictionary may contain non-result entries.

tests/conftest.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,4 +223,32 @@ def temp_data_files(tmp_path):
223223

224224
cgr_file = tmp_path / "cgr_file.cgr"
225225
cgr_file.write_text("1.0 2.0\n" "1.1 2.1\n" "1.2 2.2\n")
226+
227+
results_file = tmp_path / "fit_results.res"
228+
results_file.write_text(
229+
"""
230+
Results written: Wed Feb 25 15:14:58 2026
231+
produced by cadenmyers
232+
233+
Some quantities invalid due to missing profile uncertainty
234+
Overall (Chi2 and Reduced Chi2 invalid)
235+
------------------------------------------------------------------------------
236+
Residual 0.00000000
237+
Contributions 0.00000000
238+
Restraints 0.00000000
239+
Chi2 0.00000000
240+
Reduced Chi2 0.00000000
241+
Rw 0.00000000
242+
243+
Variables (Uncertainties invalid)
244+
------------------------------------------------------------------------------
245+
amplitude 1.00000000e+00 +/- 4.82804000e-01
246+
phase_shift -1.61291146e-18 +/- 1.00000000e+00
247+
wave_number 1.00000000e+00 +/- 2.17496687e-01
248+
249+
Variable Correlations greater than 25% (Correlations invalid)
250+
------------------------------------------------------------------------------
251+
No correlations greater than 25%
252+
"""
253+
)
226254
yield tmp_path

tests/test_fitresults.py

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,16 @@
1616

1717
import unittest
1818

19+
import numpy as np
1920
import pytest
2021
from scipy.optimize import leastsq
2122

2223
from diffpy.srfit.fitbase.fitrecipe import FitRecipe
23-
from diffpy.srfit.fitbase.fitresults import FitResults, initializeRecipe
24+
from diffpy.srfit.fitbase.fitresults import (
25+
FitResults,
26+
initializeRecipe,
27+
resultsDictionary,
28+
)
2429

2530
# The fit results from the recipe fixture in conftest.py
2631
expected_fitresults = """\
@@ -138,6 +143,69 @@ def test_save_results(build_recipe_one_contribution, tmp_path):
138143
assert expected_var in actual_results.strip()
139144

140145

146+
def test_get_results_dictionary(build_recipe_one_contribution):
147+
# Case: user gets results dictionary after optimization
148+
# expected: results dictionary contains expected keys and values
149+
recipe = build_recipe_one_contribution
150+
optimize_recipe(recipe)
151+
results = FitResults(recipe)
152+
actual_results_dict = results.get_results_dictionary()
153+
expected_results_dict = {
154+
"amplitude": 1.000000000060171,
155+
"wave_number": 1.00000000012548,
156+
"phase_shift": -1.6129114631049646e-18,
157+
"Residual": 3.3284672708760557e-19,
158+
"Contributions": 3.3284672708760557e-19,
159+
"Restraints": 0,
160+
"Chi2": 3.3284672708760557e-19,
161+
"Reduced Chi2": 4.7549532441086507e-20,
162+
"Rw": 2.7196679825449506e-10,
163+
}
164+
actual_values = np.round(np.array(list(actual_results_dict.values())), 5)
165+
actual_keys = set(actual_results_dict.keys())
166+
expected_values = np.round(
167+
np.array(list(expected_results_dict.values())), 5
168+
)
169+
expected_keys = set(expected_results_dict.keys())
170+
assert expected_keys == actual_keys
171+
assert list(expected_values == list(actual_values))
172+
173+
174+
def test_resultsDictionary(temp_data_files):
175+
# Case: user gets results dictionary from a results file
176+
# expected: results dictionary contains expected keys and values
177+
actual_results_dict = resultsDictionary(
178+
temp_data_files / "fit_results.res"
179+
)
180+
# bad behavior: values are stored as strings
181+
expected_results_dict = {
182+
"than": "25", # bad behavior: shouldn't be here
183+
"wave_number": "1.00000000e+00",
184+
"phase_shift": "-1.61291146e-18",
185+
"amplitude": "1.00000000e+00",
186+
"Rw": "0.00000000",
187+
"Chi2": "0.00000000",
188+
"Restraints": "0.00000000",
189+
"Contributions": "0.00000000",
190+
"Residual": "0.00000000",
191+
"Feb": "25", # bad behavior: shouldn't be here
192+
}
193+
# convert values to float for comparison (with rounding)
194+
for key in expected_results_dict:
195+
expected_results_dict[key] = float(expected_results_dict[key])
196+
for key in actual_results_dict:
197+
actual_results_dict[key] = float(actual_results_dict[key])
198+
199+
actual_keys = set(actual_results_dict.keys())
200+
actual_values = np.round(np.array(list(actual_results_dict.values())), 5)
201+
expected_keys = set(expected_results_dict.keys())
202+
expected_values = np.round(
203+
np.array(list(expected_results_dict.values())), 5
204+
)
205+
assert expected_keys == actual_keys
206+
assert list(expected_values == list(actual_values))
207+
208+
141209
def testInitializeFromFileName(datafile):
142210
recipe = FitRecipe("recipe")
143211
recipe.create_new_variable("A", 0)

0 commit comments

Comments
 (0)