Skip to content

Commit

Permalink
Clean up some low-hanging warnings in test suite (#310)
Browse files Browse the repository at this point in the history
* Spglib 2.5 compatibility in brille.py

Spglib 2.5 introduces dataclasses for many of its data objects, and
raises a DeprecationWarning if you try to use it as a dictionary.

That's very nice, but we'd like to support a range of versions,
so for now we convert the new classes to a dict. We can migrate when
these versions of Spglib are more established.

* Suppress Spglib 2.5 deprecation warning raised by seekpath

Maybe when seekpath fixes this we can bump both version requirements?

* Refactor how warnings are checked in some tests

* Call to tight_layout() raises warning but seems to be unnecessary

* Explicitly fill masked array values with NaN

When this is implicit, a warning is raised.

* We find that different warning messages are raised by ostensibly the
same problem (irregular bin-width when broadening), depending on the code path. That's not ideal, but can
stay for now.

* Fix a unit-strip warning in test_mul functions
  • Loading branch information
ajjackson authored Jul 24, 2024
1 parent 8c87ed6 commit 75fe42e
Show file tree
Hide file tree
Showing 11 changed files with 192 additions and 98 deletions.
6 changes: 6 additions & 0 deletions euphonic/brille.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import dataclasses
from multiprocessing import cpu_count
from typing import Union, Optional, Dict, Any, Type, TypeVar

Expand Down Expand Up @@ -185,6 +186,11 @@ def from_force_constants(
cell = crystal.to_spglib_cell()

dataset = spg.get_symmetry_dataset(cell)
# Spglib 2.5 introduced dataclass structures:
# convert back to dict for now
if dataclasses.is_dataclass(dataset):
dataset = dataclasses.asdict(dataset)

rotations = dataset['rotations'] # in fractional
translations = dataset['translations'] # in fractional

Expand Down
10 changes: 7 additions & 3 deletions euphonic/cli/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,9 +312,13 @@ def _bands_from_force_constants(data: ForceConstants,
QpointFrequencies],
XTickLabels, SplitArgs]:
structure = data.crystal.to_spglib_cell()
bandpath = seekpath.get_explicit_k_path(
structure,
reference_distance=q_distance.to('1 / angstrom').magnitude)
with warnings.catch_warnings():
# SeeK-path is raising spglib 2.5.0 deprecation warnings, we
# don't care to see those for now
warnings.simplefilter("ignore", category=DeprecationWarning)
bandpath = seekpath.get_explicit_k_path(
structure,
reference_distance=q_distance.to('1 / angstrom').magnitude)

if insert_gamma:
_insert_gamma(bandpath)
Expand Down
41 changes: 27 additions & 14 deletions tests_and_analysis/test/euphonic_test/test_qpoint_frequencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from tests_and_analysis.test.euphonic_test.test_spectrum2d import (
get_expected_spectrum2d, check_spectrum2d)
from tests_and_analysis.test.utils import (
get_data_path, get_castep_path, get_phonopy_path,
does_not_raise, get_data_path, get_castep_path, get_phonopy_path,
check_frequencies_at_qpts, check_unit_conversion,
check_json_metadata, check_property_setters, get_mode_widths)

Expand Down Expand Up @@ -555,22 +555,30 @@ def test_fast_method_called_when_selected(self, mock_fast_method):

class TestQpointFrequenciesCalculateDosMap:
@pytest.mark.parametrize(
'material, qpt_freqs_json, ebins, expected_dos_map_json', [
'material, qpt_freqs_json, ebins, expected_dos_map_json, context', [
('quartz', 'quartz_bandstructure_cv_only_qpoint_frequencies.json',
np.arange(0, 155, 0.6)*ureg('meV'),
'quartz_bandstructure_dos_map.json'),
'quartz_bandstructure_dos_map.json',
pytest.warns(
UserWarning,
match=("Could not determine cell symmetry, using generic q-point labels"))),
('quartz', 'quartz_bandstructure_cv_only_qpoint_frequencies.json',
np.concatenate((np.arange(0, 100, 0.3),
np.arange(100, 155, 0.6)))*ureg('meV'),
'quartz_bandstructure_dos_map_uneven_bins.json'),
'quartz_bandstructure_dos_map_uneven_bins.json',
pytest.warns(
UserWarning,
match=("Could not determine cell symmetry, using generic q-point labels"))),
('NaCl', 'NaCl_band_yaml_from_phonopy_qpoint_frequencies.json',
np.arange(0, 300, 5)*ureg('1/cm'),
'NaCl_band_yaml_dos_map.json')
'NaCl_band_yaml_dos_map.json',
does_not_raise())
])
def test_calculate_dos_map(
self, material, qpt_freqs_json, ebins, expected_dos_map_json):
self, material, qpt_freqs_json, ebins, expected_dos_map_json, context):
qpt_freqs = get_qpt_freqs(material, qpt_freqs_json)
dos_map = qpt_freqs.calculate_dos_map(ebins)
with context:
dos_map = qpt_freqs.calculate_dos_map(ebins)
expected_dos_map = get_expected_spectrum2d(
expected_dos_map_json)
check_spectrum2d(dos_map, expected_dos_map)
Expand Down Expand Up @@ -618,18 +626,23 @@ def test_calculate_dos_map_gives_same_result_as_dos_at_single_qpt(
class TestQpointFrequenciesGetDispersion:

@pytest.mark.parametrize(
'material, qpt_freqs_json, expected_dispersion_json', [
'material, qpt_freqs_json, expected_dispersion_json, context', [
('quartz', 'quartz_bandstructure_qpoint_frequencies.json',
'quartz_bandstructure_dispersion.json'),
'quartz_bandstructure_dispersion.json',
does_not_raise()),
('quartz', 'quartz_bandstructure_cv_only_qpoint_frequencies.json',
'quartz_bandstructure_cv_only_dispersion.json'),
'quartz_bandstructure_cv_only_dispersion.json',
pytest.warns(UserWarning,
match="Could not determine cell symmetry, using generic q-point labels")),
('NaCl', 'NaCl_band_yaml_from_phonopy_qpoint_frequencies.json',
'NaCl_band_yaml_dispersion.json')
'NaCl_band_yaml_dispersion.json',
does_not_raise())
])
def test_get_dispersion(
self, material, qpt_freqs_json, expected_dispersion_json):
qpt_freqs = get_qpt_freqs(material, qpt_freqs_json)
disp = qpt_freqs.get_dispersion()
self, material, qpt_freqs_json, expected_dispersion_json, context):
with context:
qpt_freqs = get_qpt_freqs(material, qpt_freqs_json)
disp = qpt_freqs.get_dispersion()
expected_disp = get_expected_spectrum1dcollection(
expected_dispersion_json)
check_spectrum1dcollection(disp, expected_disp)
47 changes: 27 additions & 20 deletions tests_and_analysis/test/euphonic_test/test_spectrum1d.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@
from euphonic import ureg
from euphonic.spectra import Spectrum1D
from tests_and_analysis.test.utils import (
get_data_path, get_castep_path, check_unit_conversion,
check_json_metadata, check_property_setters, get_spectrum_from_text,
check_spectrum_text_header)
check_unit_conversion,
check_spectrum_text_header,
check_json_metadata,
check_property_setters,
does_not_raise,
get_castep_path,
get_data_path,
get_spectrum_from_text)


class ExpectedSpectrum1D:
Expand Down Expand Up @@ -367,26 +372,33 @@ def test_split_errors(self, args, spectrum1d_file, expected_error):
spec1d.split(**args)

@pytest.mark.parametrize(
'args, spectrum1d_file, broadened_spectrum1d_file', [
'args, spectrum1d_file, broadened_spectrum1d_file, context', [
((1*ureg('meV'), {}),
'methane_pdos_index_1.json',
'methane_pdos_index_1_1meV_gauss_broaden.json'),
'methane_pdos_index_1_1meV_gauss_broaden.json',
does_not_raise()),
((1*ureg('meV'), {}),
'quartz_666_dos.json',
'quartz_666_1meV_gauss_broaden_dos.json'),
'quartz_666_1meV_gauss_broaden_dos.json',
does_not_raise()),
((1*ureg('meV'), {'shape':'gauss'}),
'quartz_666_dos.json',
'quartz_666_1meV_gauss_broaden_dos.json'),
'quartz_666_dos.json',
'quartz_666_1meV_gauss_broaden_dos.json',
does_not_raise()),
((1*ureg('meV'), {'shape': 'lorentz'}),
'quartz_666_dos.json',
'quartz_666_1meV_lorentz_broaden_dos.json'),
'quartz_666_dos.json',
'quartz_666_1meV_lorentz_broaden_dos.json',
does_not_raise()),
((1*ureg('meV'), {'method': 'convolve'}),
'toy_quartz_cropped_uneven_dos.json',
'toy_quartz_cropped_uneven_broaden_dos.json')])
def test_broaden(self, args, spectrum1d_file, broadened_spectrum1d_file):
'toy_quartz_cropped_uneven_broaden_dos.json',
pytest.warns(UserWarning, match="x_data bin widths are not equal"))])
def test_broaden(
self, args, spectrum1d_file, broadened_spectrum1d_file, context):
spec1d = get_spectrum1d(spectrum1d_file)
expected_broadened_spec1d = get_spectrum1d(broadened_spectrum1d_file)
broadened_spec1d = spec1d.broaden(args[0], **args[1])
with context:
broadened_spec1d = spec1d.broaden(args[0], **args[1])
check_spectrum1d(broadened_spec1d, expected_broadened_spec1d)

def test_broaden_invalid_shape_raises_value_error(self):
Expand All @@ -404,11 +416,6 @@ def test_broaden_uneven_bins_deprecation_raises_value_error(self):
with pytest.raises(ValueError):
spec1d.broaden(1*ureg('meV'))

def test_broaden_uneven_bins_and_explicit_convolve_warns(self):
spec1d = get_spectrum1d('toy_quartz_cropped_uneven_dos.json')
with pytest.warns(UserWarning):
spec1d.broaden(1*ureg('meV'), method='convolve')

def test_variable_broadening_consistent(self):
"""Check variable broadening is consistent with fixed-width method"""
spec1d = get_spectrum1d('quartz_666_dos.json')
Expand Down Expand Up @@ -506,8 +513,8 @@ def test_add_metadata(self, spectrum_files, metadata,
def test_mul(self):
spec = get_spectrum1d('xsq_spectrum1d.json')

npt.assert_allclose(spec.y_data * 2.,
(spec * 2.).y_data)
npt.assert_allclose(spec.y_data.magnitude * 2.,
(spec * 2.).y_data.magnitude)

check_spectrum1d(spec, (spec * 2.) * 0.5)

Expand Down
53 changes: 36 additions & 17 deletions tests_and_analysis/test/euphonic_test/test_spectrum2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@
from euphonic import ureg
from euphonic.spectra import Spectrum2D, apply_kinematic_constraints
from tests_and_analysis.test.utils import (
get_data_path, check_unit_conversion, check_json_metadata,
check_property_setters)
check_unit_conversion,
check_json_metadata,
check_property_setters,
does_not_raise,
get_data_path,
)


class ExpectedSpectrum2D:
Expand Down Expand Up @@ -311,56 +315,71 @@ def test_split(self, args, spectrum2d_file, split_spectrum_files):
check_spectrum2d(spectrum, expected_spectrum)

@pytest.mark.parametrize(
'args, spectrum2d_file, broadened_spectrum2d_file', [
'args, spectrum2d_file, broadened_spectrum2d_file, context', [
(({'x_width': 0.1*ureg('1/angstrom'), 'method': 'convolve'}),
'quartz_bandstructure_sqw.json',
'quartz_bandstructure_0.1ang_xbroaden_sqw.json'),
'quartz_bandstructure_0.1ang_xbroaden_sqw.json',
pytest.warns(UserWarning,
match="x_data bin widths are not equal")),
(({'y_width': 2*ureg('meV')}),
'quartz_bandstructure_sqw.json',
'quartz_bandstructure_2meV_ybroaden_sqw.json'),
'quartz_bandstructure_2meV_ybroaden_sqw.json',
does_not_raise()),
(({'x_width': 0.1*ureg('1/angstrom'), 'y_width': 2*ureg('meV'),
'method': 'convolve'}),
'quartz_bandstructure_sqw.json',
'quartz_bandstructure_2meV_0.1ang_xybroaden_sqw.json'),
'quartz_bandstructure_2meV_0.1ang_xybroaden_sqw.json',
pytest.warns(UserWarning,
match="x_data bin widths are not equal")),
(({'x_width': 0.1*ureg('1/angstrom'), 'y_width': 2*ureg('meV'),
'shape': 'lorentz', 'method': 'convolve'}),
'quartz_bandstructure_sqw.json',
'quartz_bandstructure_xybroaden_lorentz_sqw.json'),
'quartz_bandstructure_xybroaden_lorentz_sqw.json',
pytest.warns(UserWarning,
match="x_data bin widths are not equal")),
(({'x_width': 0.2*ureg('1/angstrom'), 'y_width': 1.5*ureg('meV'),
'shape': 'gauss'}),
'lzo_57L_bragg_sqw.json',
'lzo_57L_1.5meV_0.1ang_gauss_sqw.json'),
'lzo_57L_1.5meV_0.1ang_gauss_sqw.json',
pytest.warns(UserWarning,
match="Not all x-axis bins are the same width")),
(({'x_width': 0.2*ureg('1/angstrom'), 'y_width': 1.5*ureg('meV'),
'shape': 'lorentz'}),
'lzo_57L_bragg_sqw.json',
'lzo_57L_1.5meV_0.1ang_lorentz_sqw.json'),
'lzo_57L_1.5meV_0.1ang_lorentz_sqw.json',
pytest.warns(UserWarning,
match="Not all x-axis bins are the same width")),
(({'x_width': (lambda x: np.polyval([0.2, -0.5],
x.to('1/nm').magnitude
) * ureg('1/nm')),
'y_width': (lambda y: np.polyval([0., -0.4, 3.],
y.to('J').magnitude
) * ureg('J')),
'width_fit': 'cubic'},
'synthetic_x.json', 'synthetic_x_poly_broadened.json')),
'synthetic_x.json', 'synthetic_x_poly_broadened.json',
does_not_raise())),
(({'x_width': (lambda x: np.polyval([0.2, -0.5],
x.to('1/nm').magnitude
) * ureg('1/nm')),
'y_width': (lambda y: np.polyval([0., -0.4, 3.],
y.to('J').magnitude
) * ureg('J')),
'width_fit': 'cheby-log'},
'synthetic_x.json', 'synthetic_x_poly_broadened_cheby.json')),
'synthetic_x.json', 'synthetic_x_poly_broadened_cheby.json',
does_not_raise())),
])
def test_broaden(self, args, spectrum2d_file, broadened_spectrum2d_file):
def test_broaden(self, args, spectrum2d_file, broadened_spectrum2d_file,
context):
spec2d = get_spectrum2d(spectrum2d_file)
expected_broadened_spec2d = get_spectrum2d(broadened_spectrum2d_file)
broadened_spec2d = spec2d.broaden(**args)
with context:
broadened_spec2d = spec2d.broaden(**args)
check_spectrum2d(broadened_spec2d, expected_broadened_spec2d)

def test_broaden_invalid_shape_raises_value_error(self):
spec2d = get_spectrum2d('quartz_bandstructure_sqw.json')
with pytest.raises(ValueError):
spec2d.broaden(x_width=1*ureg('meV'), shape='unknown')
with pytest.raises(ValueError), pytest.warns(UserWarning):
spec2d.broaden(x_width=1*ureg('meV'), shape='unknown')

def test_broaden_uneven_bins_deprecation_raises_value_error(self):
spec2d = get_spectrum2d('La2Zr2O7_cut_sqw_uneven_bins.json')
Expand Down Expand Up @@ -478,8 +497,8 @@ def test_get_bin_centres_with_invalid_data_shape_raises_value_error(
def test_mul(self):
spec = get_spectrum2d('example_spectrum2d.json')

npt.assert_allclose(spec.z_data * 2.,
(spec * 2.).z_data)
npt.assert_allclose(spec.z_data.magnitude * 2.,
(spec * 2.).z_data.magnitude)

check_spectrum2d(spec, (spec * 2.) * 0.5)

Expand Down
64 changes: 39 additions & 25 deletions tests_and_analysis/test/euphonic_test/test_util.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Unit tests for euphonic.util"""

import json
import os
import sys
Expand All @@ -9,7 +11,7 @@
from euphonic import ureg
from euphonic.util import (direction_changed, mp_grid, get_qpoint_labels,
mode_gradients_to_widths, convert_fc_phases)
from tests_and_analysis.test.utils import get_data_path
from tests_and_analysis.test.utils import does_not_raise, get_data_path
from tests_and_analysis.test.euphonic_test.test_crystal import get_crystal
from tests_and_analysis.test.euphonic_test.test_force_constants import (
get_fc_path, get_fc)
Expand Down Expand Up @@ -42,30 +44,42 @@ def test_444_grid(self):

class TestGetQptLabels:

@pytest.mark.parametrize('qpts, kwargs, expected_labels', [
(np.array([[0.5, 0.5, 0.5], [0.0, 0.0, 0.5]]),
{'cell': get_crystal('quartz').to_spglib_cell()},
[(0, ''), (1, 'A')]),
(np.array([[0.5, 0.5, 0.5], [0.4, 0.4, 0.5], [0.3, 0.3, 0.5],
[0.2, 0.2, 0.5], [0.1, 0.1, 0.5], [0.0, 0.0, 0.5]]),
{'cell': get_crystal('quartz').to_spglib_cell()},
[(0, ''), (5, 'A')]),
(np.array([[0.0, 0.0, 0.0], [0.0, 0.0, 0.1], [0.0, 0.0, 0.2],
[0.0, 0.0, 0.3], [0.0, 0.0, 0.4], [0.0, 0.0, 0.5],
[0.125, 0.25, 0.5], [0.25, 0.5, 0.5], [0.375, 0.75, 0.5]]),
{},
[(0, '0 0 0'), (5, '0 0 1/2'), (8, '3/8 3/4 1/2')]),
(np.array([[0.0, 0.0, 0.0], [0.0, 0.0, 0.1], [0.0, 0.0, 0.2],
[0.0, 0.0, 0.3], [0.0, 0.0, 0.4], [0.0, 0.0, 0.5],
[0.125, 0.25, 0.5], [0.25, 0.5, 0.5], [0.375, 0.75, 0.5]]),
{'cell': get_crystal('quartz_cv_only').to_spglib_cell()},
[(0, '0 0 0'), (5, '0 0 1/2'), (8, '3/8 3/4 1/2')]),
(np.array([[0.0, 0., 0.], [0.25, 0., 0.], [0.25, 0., 0.], [0.3, 0., 0.],
[0.5, 0., 0.], [0.5, 0.1, 0.], [0.5, 0.25, 0.]]),
{},
[(0, '0 0 0'), (1, '1/4 0 0'), (4, '1/2 0 0'), (6, '1/2 1/4 0')])])
def test_get_qpt_labels(self, qpts, kwargs, expected_labels):
labels = get_qpoint_labels(qpts, **kwargs)
@pytest.mark.parametrize(
'qpts, kwargs, expected_labels, context',
[(np.array([[0.5, 0.5, 0.5], [0.0, 0.0, 0.5]]),
{'cell': get_crystal('quartz').to_spglib_cell()},
[(0, ''), (1, 'A')],
does_not_raise()),
(np.array([[0.5, 0.5, 0.5], [0.4, 0.4, 0.5], [0.3, 0.3, 0.5],
[0.2, 0.2, 0.5], [0.1, 0.1, 0.5], [0.0, 0.0, 0.5]]),
{'cell': get_crystal('quartz').to_spglib_cell()},
[(0, ''), (5, 'A')],
does_not_raise()),
(np.array([[0.0, 0.0, 0.0], [0.0, 0.0, 0.1], [0.0, 0.0, 0.2],
[0.0, 0.0, 0.3], [0.0, 0.0, 0.4], [0.0, 0.0, 0.5],
[0.125, 0.25, 0.5], [0.25, 0.5, 0.5], [0.375, 0.75, 0.5]]),
{},
[(0, '0 0 0'), (5, '0 0 1/2'), (8, '3/8 3/4 1/2')],
does_not_raise()),
(np.array([[0.0, 0.0, 0.0], [0.0, 0.0, 0.1], [0.0, 0.0, 0.2],
[0.0, 0.0, 0.3], [0.0, 0.0, 0.4], [0.0, 0.0, 0.5],
[0.125, 0.25, 0.5], [0.25, 0.5, 0.5], [0.375, 0.75, 0.5]]),
{'cell': get_crystal('quartz_cv_only').to_spglib_cell()},
[(0, '0 0 0'), (5, '0 0 1/2'), (8, '3/8 3/4 1/2')],
pytest.warns(
UserWarning,
match="Could not determine cell symmetry, using generic q-point labels")),
(np.array([[0.0, 0., 0.], [0.25, 0., 0.], [0.25, 0., 0.],
[0.3, 0., 0.], [0.5, 0., 0.], [0.5, 0.1, 0.],
[0.5, 0.25, 0.]]),
{},
[(0, '0 0 0'), (1, '1/4 0 0'), (4, '1/2 0 0'), (6, '1/2 1/4 0')],
does_not_raise())])
def test_get_qpt_labels(
self, qpts, kwargs, expected_labels, context):
with context:
labels = get_qpoint_labels(qpts, **kwargs)

assert labels == expected_labels


Expand Down
Loading

0 comments on commit 75fe42e

Please sign in to comment.