diff --git a/news/deprecate-symmetryutilities-7.rst b/news/deprecate-symmetryutilities-7.rst new file mode 100644 index 0000000..e014dac --- /dev/null +++ b/news/deprecate-symmetryutilities-7.rst @@ -0,0 +1,27 @@ +**Added:** + +* Added ``position_formulas`` method in ``SymmetryConstraints`` class +* Added ``position_formulas_pruned`` method in ``SymmetryConstraints`` class +* Added ``u_formulas_pruned`` method in ``SymmetryConstraints`` class + +**Changed:** + +* + +**Deprecated:** + +* Deprecated ``positionFormulas`` method in ``SymmetryConstraints`` class for removal in version 4.0.0 +* Deprecated ``positionFormulasPruned`` method in ``SymmetryConstraints`` class for removal in version 4.0.0 +* Deprecated ``UFormulasPruned`` method in ``SymmetryConstraints`` class for removal in version 4.0.0 + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* diff --git a/src/diffpy/structure/symmetryutilities.py b/src/diffpy/structure/symmetryutilities.py index b596e17..5e744fb 100644 --- a/src/diffpy/structure/symmetryutilities.py +++ b/src/diffpy/structure/symmetryutilities.py @@ -1074,6 +1074,24 @@ def prune_formula_dictionary(eqdict): "u_formulas", removal_version, ) +positionFormulas_deprecation_msg = build_deprecation_message( + symmetry_constraints, + "positionFormulas", + "position_formulas", + removal_version, +) +positionFormulasPruned_deprecation_msg = build_deprecation_message( + symmetry_constraints, + "positionFormulasPruned", + "position_formulas_pruned", + removal_version, +) +UFormulasPruned_deprecation_msg = build_deprecation_message( + symmetry_constraints, + "UFormulasPruned", + "u_formulas_pruned", + removal_version, +) class SymmetryConstraints(object): @@ -1243,7 +1261,16 @@ def pos_parm_values(self): """Return list of position parameters values.""" return [v for n, v in self.pospars] + @deprecated(posparValues_deprecation_msg) def positionFormulas(self, xyzsymbols=None): + """'diffpy.structure.SymmetryConstraints.positionFormulas' is + deprecated and will be removed in version 4.0.0. + + Please use 'diffpy.structure.SymmetryConstraints.position_formulas' instead. + """ + return self.position_formulas(xyzsymbols) + + def position_formulas(self, xyzsymbols=None): """List of position formulas with custom parameter symbols. Parameters @@ -1279,7 +1306,16 @@ def translatesymbol(matchobj): rv.append(treqns) return rv + @deprecated(positionFormulasPruned_deprecation_msg) def positionFormulasPruned(self, xyzsymbols=None): + """'diffpy.structure.SymmetryConstraints.positionFormulasPruned' + is deprecated and will be removed in version 4.0.0. + + Please use 'diffpy.structure.SymmetryConstraints.position_formulas_pruned' instead. + """ + return self.position_formulas_pruned(xyzsymbols) + + def position_formulas_pruned(self, xyzsymbols=None): """List of position formula dictionaries with constant items removed. @@ -1297,7 +1333,7 @@ def positionFormulasPruned(self, xyzsymbols=None): list List of coordinate formula dictionaries. """ - rv = [prune_formula_dictionary(eqns) for eqns in self.positionFormulas(xyzsymbols)] + rv = [prune_formula_dictionary(eqns) for eqns in self.position_formulas(xyzsymbols)] return rv @deprecated(UparSymbols_deprecation_msg) @@ -1376,7 +1412,17 @@ def translatesymbol(matchobj): rv.append(treqns) return rv + @deprecated(UFormulasPruned_deprecation_msg) def UFormulasPruned(self, Usymbols=None): + """'diffpy.structure.SymmetryConstraints.UFormulasPruned' is + deprecated and will be removed in version 4.0.0. + + Please use 'diffpy.structure.SymmetryConstraints.u_formulas_pruned' + instead. + """ + return self.u_formulas_pruned(Usymbols) + + def u_formulas_pruned(self, Usymbols=None): """List of atom displacement formula dictionaries with constant items removed. diff --git a/tests/test_symmetryutilities.py b/tests/test_symmetryutilities.py index 8fd2d5c..b767190 100644 --- a/tests/test_symmetryutilities.py +++ b/tests/test_symmetryutilities.py @@ -22,6 +22,7 @@ import pytest from diffpy.structure.spacegroups import GetSpaceGroup +from diffpy.structure.structureerrors import SymmetryError from diffpy.structure.symmetryutilities import ( ExpandAsymmetricUnit, GeneratorSite, @@ -960,6 +961,69 @@ def test_posparSymbols_and_posparValues(self): assert expected_symbols == actual_symbols assert expected_values == actual_values + def test_positionFormulas(self): + sg225 = GetSpaceGroup(225) + eau = ExpandAsymmetricUnit(sg225, [[0, 0, 0]]) + sc = SymmetryConstraints(sg225, eau.expandedpos) + # C1: Simulate the "not enough symbols" branch + sc.pospars = [("x1", 0.12), ("y1", 0.34), ("z1", 0.56)] + sc.poseqns = [ + {"x": "x1", "y": "y1 +0.5", "z": "-z1 +0.25"}, + {"x": "-x1 +0.5", "y": "y1", "z": "z1 +0.5"}, + ] + with pytest.raises(SymmetryError): + sc.positionFormulas(["x1"]) # too few custom symbols + # C2: Normal case, does substitution of x0/y0/z0 tokens in formulas + # Make pospars consistent with what positionFormulas expects to replace + actual = sc.positionFormulas(["xA", "yA", "zA"]) + expected = [ + {"x": "xA", "y": "yA +0.5", "z": "-zA +0.25"}, + {"x": "-xA +0.5", "y": "yA", "z": "zA +0.5"}, + ] + assert actual == expected + + def test_positionFormulasPruned(self): + sg225 = GetSpaceGroup(225) + eau = ExpandAsymmetricUnit(sg225, [[0, 0, 0]]) + sc = SymmetryConstraints(sg225, eau.expandedpos) + # C1: Remove any key-value pairs with constant values + sc.pospars = [("x1", 0.12), ("y1", 0.34), ("z1", 0.56)] + sc.poseqns = [ + {"x": "x1", "y": "0.25", "z": "-z1 +0.5"}, + {"x": "0", "y": "y1 +0.5", "z": "0.125"}, + ] + actual = sc.positionFormulasPruned(["xA", "yA", "zA"]) + expected = [ + {"x": "xA", "z": "-zA +0.5"}, + {"y": "yA +0.5"}, + ] + assert actual == expected + + def test_UFormulasPruned(self): + """Check SymmetryConstraints.UFormulasPruned()""" + u_formulas = { + "U11": "A", + "U22": "A", + "U33": "C", + "U12": "0.5*A", + "U13": "0", + "U23": "0", + } + expected = [ + { + "U11": "A", + "U22": "A", + "U33": "C", + "U12": "0.5*A", + } + ] + sg225 = GetSpaceGroup(225) + eau = ExpandAsymmetricUnit(sg225, [[0, 0, 0]]) + sc = SymmetryConstraints(sg225, eau.expandedpos) + sc.Ueqns = [u_formulas] + actual = sc.UFormulasPruned(u_formulas) + assert actual == expected + # def test_UFormulas(self): # """check SymmetryConstraints.UFormulas() @@ -1113,5 +1177,112 @@ def test_pospar_symbols_and_pospar_values(params, expected_symbols, expected_val assert actual_values == expected_values +@pytest.mark.parametrize( + "params", + [ + pytest.param(["x1"]), + ], +) +def test_position_formulas_raises_SymmetryError(params): + sg225 = GetSpaceGroup(225) + eau = ExpandAsymmetricUnit(sg225, [[0, 0, 0]]) + sc = SymmetryConstraints(sg225, eau.expandedpos) + sc.pospars = [("x1", 0.12), ("y1", 0.34), ("z1", 0.56)] + sc.poseqns = [ + {"x": "x1", "y": "y1 +0.5", "z": "-z1 +0.25"}, + {"x": "-x1 +0.5", "y": "y1", "z": "z1 +0.5"}, + ] + # C1: Simulate the "not enough symbols" in position_formula + with pytest.raises(SymmetryError): + sc.position_formulas(params) + + +@pytest.mark.parametrize( + "params, expected", + [ + pytest.param( # C2: Normal case, does substitution of x1/y1/z1 tokens in formulas + # Make pospars consistent with what position_formulas expects to replace + ["xA", "yA", "zA"], + [ + {"x": "xA", "y": "yA +0.5", "z": "-zA +0.25"}, + {"x": "-xA +0.5", "y": "yA", "z": "zA +0.5"}, + ], + ), + ], +) +def test_position_formulas(params, expected): + sg225 = GetSpaceGroup(225) + eau = ExpandAsymmetricUnit(sg225, [[0, 0, 0]]) + sc = SymmetryConstraints(sg225, eau.expandedpos) + sc.pospars = [("x1", 0.12), ("y1", 0.34), ("z1", 0.56)] + sc.poseqns = [ + {"x": "x1", "y": "y1 +0.5", "z": "-z1 +0.25"}, + {"x": "-x1 +0.5", "y": "y1", "z": "z1 +0.5"}, + ] + actual = sc.position_formulas(params) + assert actual == expected + + +@pytest.mark.parametrize( + "poseqns, expected", + [ + pytest.param( + [ + {"x": "x1", "y": "0.25", "z": "-z1 +0.5"}, + {"x": "0", "y": "y1 +0.5", "z": "0.125"}, + ], + [ + {"x": "xA", "z": "-zA +0.5"}, + {"y": "yA +0.5"}, + ], + ) + ], +) +def test_position_formulas_pruned(poseqns, expected): + sg225 = GetSpaceGroup(225) + eau = ExpandAsymmetricUnit(sg225, [[0, 0, 0]]) + sc = SymmetryConstraints(sg225, eau.expandedpos) + + sc.pospars = [("x1", 0.12), ("y1", 0.34), ("z1", 0.56)] + sc.poseqns = poseqns + + actual = sc.position_formulas_pruned(["xA", "yA", "zA"]) + assert actual == expected + + +@pytest.mark.parametrize( + "u_formulas, expected", + [ + pytest.param( + [ + { + "U11": "A", + "U22": "A", + "U33": "C", + "U12": "0.5*A", + "U13": "0", + "U23": "0", + } + ], + [ + { + "U11": "A", + "U22": "A", + "U33": "C", + "U12": "0.5*A", + } + ], + ) + ], +) +def test_u_formula_pruned(u_formulas, expected): + sg225 = GetSpaceGroup(225) + eau = ExpandAsymmetricUnit(sg225, [[0, 0, 0]]) + sc = SymmetryConstraints(sg225, eau.expandedpos) + sc.Ueqns = u_formulas + actual = sc.u_formulas_pruned(u_formulas) + assert actual == expected + + if __name__ == "__main__": unittest.main()