Skip to content

Commit 5b3cea3

Browse files
committed
Refactor FORCECONSTANTS validation logic, add unit tests
1 parent af099db commit 5b3cea3

File tree

4 files changed

+63
-31
lines changed

4 files changed

+63
-31
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ce75e1d1d4e693a320349b2e996f6d4a
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
5e3f4a778792461cfa47d5b5d1003309

scripts/abins/abinsalgorithm.py

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -840,39 +840,45 @@ def _validate_euphonic_input_file(cls, filename_full_path: str) -> dict:
840840

841841
if (suffix := path.suffix) == ".castep_bin":
842842
# Assume any .castep_bin file is valid choice
843-
pass
844-
845-
elif suffix in (".yaml", ".yml"):
846-
# Check .yaml files have expected keys for Phonopy force constants
847-
with open(filename_full_path, "r") as yaml_file:
848-
phonon_data = yaml.load(yaml_file, Loader=SafeLoader)
849-
850-
if {"phonopy", "force_constants"}.issubset(phonon_data):
851-
pass
852-
853-
elif "phonopy" in phonon_data:
854-
# Phonopy file without force constants: they must be in another file
855-
856-
# Check if following janus conventions:
857-
# /parent/seedname-phonopy.yml -> /parent/seedname-force_constants.hdf5
858-
janus_phonopy_re = "(?P<seedname>.+)-phonopy.yml"
859-
fc_filenames = ("FORCE_CONSTANTS", "force_constants.hdf5")
860-
if re_match := re.match(janus_phonopy_re, path.name):
861-
fc_file = path.parent / f"{re_match['seedname']}-force_constants.hdf5"
862-
if not fc_file.is_file():
863-
return dict(
864-
Invalid=True,
865-
Comment=f"Could not find force constants in {filename_full_path}, or find data file {fc_file}",
866-
)
843+
return dict(Invalid=False, Comment="")
867844

868-
# Otherwise FC could be in a FORCE_CONSTANTS or force_constants.hdf5 file
869-
elif not any(map(lambda fc_filename: (path.parent / fc_filename).is_file(), fc_filenames)):
870-
return dict(
871-
Invalid=True,
872-
Comment=f"Could not find force constants in {filename_full_path}, or find data file {' or '.join(fc_filenames)}",
873-
)
845+
if suffix not in (".yaml", ".yml"):
846+
return dict(Invalid=True, Comment="Invalid extension: FORCECONSTANTS requires .castep_bin, .yaml or .yml")
847+
848+
# Check .yaml files have expected keys for Phonopy force constants
849+
with open(filename_full_path, "r") as yaml_file:
850+
phonon_data = yaml.load(yaml_file, Loader=SafeLoader)
851+
852+
if {"phonopy", "force_constants"}.issubset(phonon_data):
853+
# Force constants are in the yaml file: good
854+
return dict(Invalid=False, Comment="")
855+
856+
if "phonopy" not in phonon_data:
857+
# Not a Phonopy file: can't use this
858+
return dict(Invalid=True, Comment=f"No 'phonopy' section found in {filename_full_path}")
859+
860+
# Phonopy file without force constants: they must be in another file
861+
862+
# Check if following janus conventions:
863+
# /parent/seedname-phonopy.yml -> /parent/seedname-force_constants.hdf5
864+
janus_phonopy_re = "(?P<seedname>.+)-phonopy.yml"
865+
fc_filenames = ("FORCE_CONSTANTS", "force_constants.hdf5")
866+
if re_match := re.match(janus_phonopy_re, path.name):
867+
fc_file = path.parent / f"{re_match['seedname']}-force_constants.hdf5"
868+
if not fc_file.is_file():
869+
return dict(
870+
Invalid=True,
871+
Comment=f"Could not find force constants in {filename_full_path}, or find data file {fc_file}",
872+
)
873+
874+
# Otherwise FC could be in a FORCE_CONSTANTS or force_constants.hdf5 file
875+
elif not any(map(lambda fc_filename: (path.parent / fc_filename).is_file(), fc_filenames)):
876+
return dict(
877+
Invalid=True,
878+
Comment=f"Could not find force constants in {filename_full_path}, or find data file {' or '.join(fc_filenames)}",
879+
)
874880

875-
# Did not return already: No problems found
881+
# Phonopy YAML with available force constants
876882
return dict(Invalid=False, Comment="")
877883

878884
@classmethod

scripts/test/Abins/AbinsAlgorithmTest.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,30 @@ def test_bad_atom_info(self):
4242
species.neutron_data
4343

4444

45+
class AbinsAlgorithmValidatorsTest(unittest.TestCase):
46+
"""Test input validators"""
47+
48+
def test_validate_euphonic_yml(self):
49+
"""Check that force constants are located for .yml input"""
50+
# with open(abins.test_helpers.find_file(seedname + "_data.txt")) as data_file:
51+
# def _validate_euphonic_input_file(cls, filename_full_path: str) -> dict:
52+
from abins.test_helpers import find_file
53+
54+
issues = AbinsAlgorithm._validate_euphonic_input_file(find_file("Al_LoadPhonopy.yaml"))
55+
self.assertEqual(issues, {"Invalid": False, "Comment": ""})
56+
57+
issues = AbinsAlgorithm._validate_euphonic_input_file(find_file("Ge-phonopy.yml"))
58+
self.assertEqual(issues, {"Invalid": False, "Comment": ""})
59+
60+
issues = AbinsAlgorithm._validate_euphonic_input_file(find_file("Si2-phonon_LoadCASTEP.phonon"))
61+
self.assertEqual(issues, {"Invalid": True, "Comment": "Invalid extension: FORCECONSTANTS requires .castep_bin, .yaml or .yml"})
62+
63+
# Non-phonopy yaml from another test
64+
wrong_yaml = find_file("ISISPowderRunDetailsTestCallable.yaml")
65+
issues = AbinsAlgorithm._validate_euphonic_input_file(wrong_yaml)
66+
self.assertEqual(issues, {"Invalid": True, "Comment": f"No 'phonopy' section found in {wrong_yaml}"})
67+
68+
4569
class AbinsAlgorithmMethodsTest(unittest.TestCase):
4670
"""Test static methods on AbinsAlgorithm"""
4771

0 commit comments

Comments
 (0)