-
Notifications
You must be signed in to change notification settings - Fork 15
Refactor CLI utils module #481
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ajjackson
wants to merge
13
commits into
release-2.0.0
Choose a base branch
from
mccabe
base: release-2.0.0
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
5bd65ae
CHANGELOG update
ajjackson 6f56663
Add missing changelog note for error messages
ajjackson bf6dd38
Split euphonic.cli.utils to submodules
ajjackson 53a224e
Factor out remaining functions from cli/utils/__init__.py
ajjackson 56873c4
Remove irrelevant stuff from __all__
ajjackson 881f280
Update CHANGELOG
ajjackson 636a080
Fix mocked class import location
ajjackson c5d2a21
Little bits of cleanup from code review
ajjackson f0604a8
Early return, reduce indentation
ajjackson 7ff9d99
Apply suggestions from code review
ajjackson 77cdba6
More precise type annotation, early-return logic
ajjackson e643b5d
Ruff
ajjackson dd15873
Better use of pathlib
ajjackson File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| from ._band_structure import ( | ||
| _bands_from_force_constants, | ||
| _convert_labels_to_fractions, | ||
| _get_break_points, | ||
| _get_tick_labels, | ||
| _insert_gamma, | ||
| ) | ||
| from ._cli_parser import _get_cli_parser | ||
| from ._dw import _get_debye_waller | ||
| from ._grids import _get_energy_bins, _get_q_distance, _grid_spec_from_args | ||
| from ._kwargs import ( | ||
| _brille_calc_modes_kwargs, | ||
| _calc_modes_kwargs, | ||
| _plot_label_kwargs, | ||
| ) | ||
| from ._loaders import load_data_from_file | ||
| from ._pdos import _arrange_pdos_groups, _get_pdos_weighting | ||
| from ._plotting import _compose_style, _get_title, matplotlib_save_or_show | ||
|
|
||
| __all__ = [ | ||
| '_arrange_pdos_groups', | ||
| '_bands_from_force_constants', | ||
| '_brille_calc_modes_kwargs', | ||
| '_calc_modes_kwargs', | ||
| '_compose_style', | ||
| '_convert_labels_to_fractions', | ||
| '_get_break_points', | ||
| '_get_cli_parser', | ||
| '_get_debye_waller', | ||
| '_get_energy_bins', | ||
| '_get_pdos_weighting', | ||
| '_get_q_distance', | ||
| '_get_tick_labels', | ||
| '_get_title', | ||
| '_grid_spec_from_args', | ||
| '_insert_gamma', | ||
| '_plot_label_kwargs', | ||
| 'load_data_from_file', | ||
| 'matplotlib_save_or_show', | ||
| ] | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,164 @@ | ||
| """Band structure utilities""" | ||
|
|
||
| from collections.abc import Iterable, Sequence | ||
| from fractions import Fraction | ||
| from typing import Any, TypedDict | ||
|
|
||
| import numpy as np | ||
| import seekpath | ||
|
|
||
| from euphonic import ( | ||
| ForceConstants, | ||
| QpointFrequencies, | ||
| QpointPhononModes, | ||
| Quantity, | ||
| ) | ||
| from euphonic.util import ( | ||
| spglib_new_errors, | ||
| ) | ||
|
|
||
|
|
||
| def _get_tick_labels(bandpath: dict) -> list[tuple[int, str]]: | ||
| """Convert x-axis labels from seekpath format to euphonic format | ||
|
|
||
| i.e.:: | ||
|
|
||
| ['L', '', '', 'X', '', 'GAMMA'] --> | ||
|
|
||
| [(0, 'L'), (3, 'X'), (5, '$\\Gamma$')] | ||
| """ | ||
| label_indices = np.where(bandpath['explicit_kpoints_labels'])[0] | ||
| labels = (r'$\Gamma$' if label == 'GAMMA' else label | ||
| for label in | ||
| np.take(bandpath['explicit_kpoints_labels'], label_indices)) | ||
| return list(zip(label_indices, labels, strict=True)) | ||
|
|
||
|
|
||
| def _get_break_points(bandpath: dict) -> list[int]: | ||
| """Get information about band path labels and break points | ||
|
|
||
| Parameters | ||
| ---------- | ||
| bandpath | ||
| Bandpath dictionary from Seekpath | ||
|
|
||
| Returns | ||
| ------- | ||
| break_points | ||
| Indices at which the spectrum should be split into subplots | ||
| """ | ||
| # Find break points between continuous spectra: wherever there are two | ||
| # adjacent labels | ||
| labels = np.array(bandpath['explicit_kpoints_labels']) | ||
|
|
||
| special_point_bools = np.fromiter( | ||
| map(bool, labels), dtype=bool) | ||
|
|
||
| # [T F F T T F T] -> [F F T T F T] AND [T F F T T F] = [F F F T F F] -> 3, | ||
| adjacent_non_empty_labels = ( | ||
| special_point_bools[:-1] & special_point_bools[1:] | ||
| ) | ||
|
|
||
| adjacent_different_labels = (labels[:-1] != labels[1:]) | ||
|
|
||
| break_points = np.where( | ||
| adjacent_non_empty_labels & adjacent_different_labels, | ||
| )[0] | ||
| return (break_points + 1).tolist() | ||
|
|
||
|
|
||
| def _insert_gamma(bandpath: dict) -> None: | ||
| """Modify seekpath.get_explicit_k_path() results; duplicate Gamma | ||
|
|
||
| This enables LO-TO splitting to be included | ||
| """ | ||
| import numpy as np | ||
| gamma_indices = np.where( | ||
| np.array(bandpath['explicit_kpoints_labels'][1:-1]) == 'GAMMA', | ||
| )[0] + 1 | ||
|
|
||
| rel_kpts = bandpath['explicit_kpoints_rel'].tolist() | ||
| labels = bandpath['explicit_kpoints_labels'] | ||
| for i in reversed(gamma_indices.tolist()): | ||
| rel_kpts.insert(i, [0., 0., 0.]) | ||
| labels.insert(i, 'GAMMA') | ||
|
|
||
| bandpath['explicit_kpoints_rel'] = np.array(rel_kpts) | ||
| bandpath['explicit_kpoints_labels'] = labels | ||
|
|
||
| # These unused properties have been invalidated: safer | ||
| # to leave None than incorrect values | ||
| bandpath['explicit_kpoints_abs'] = None | ||
| bandpath['explicit_kpoints_linearcoord'] = None | ||
| bandpath['explicit_segments'] = None | ||
|
|
||
|
|
||
| XTickLabels = list[tuple[int, str]] | ||
| SplitArgs = dict[str, Any] | ||
|
|
||
|
|
||
| # Dictionary returned by seekpath.get_explicit_k_path_orig_cell | ||
| # Not a complete specification, but these are the parts we care about. | ||
| class BandpathDict(TypedDict, total=False): | ||
| explicit_kpoints_labels: Sequence[str] | ||
| explicit_kpoints_rel: Iterable[float] | ||
| is_supercell: bool | ||
|
|
||
|
|
||
| def _convert_labels_to_fractions( | ||
| bandpath: BandpathDict, *, limit: int = 32) -> None: | ||
| """Replace high-symmetry labels in seekpath data with simple fractions | ||
|
|
||
| bandpath: | ||
| dict from seekpath.get_explicit_k_path_orig_cell | ||
|
|
||
| limit: | ||
| maximum numerator value for float rounded to fraction | ||
| """ | ||
| for i, (label, qpt) in enumerate(zip(bandpath['explicit_kpoints_labels'], | ||
| bandpath['explicit_kpoints_rel'], | ||
| strict=True)): | ||
| if label: | ||
| qpt_label = ' '.join(str(Fraction(x).limit_denominator(limit)) | ||
| for x in qpt) | ||
| bandpath['explicit_kpoints_labels'][i] = qpt_label | ||
|
|
||
|
|
||
| def _bands_from_force_constants(data: ForceConstants, | ||
| q_distance: Quantity, | ||
| insert_gamma: bool = True, | ||
| frequencies_only: bool = False, | ||
| **calc_modes_kwargs, | ||
| ) -> tuple[QpointPhononModes | QpointFrequencies, XTickLabels, SplitArgs]: | ||
| structure = data.crystal.to_spglib_cell() | ||
| with spglib_new_errors(): | ||
| bandpath = seekpath.get_explicit_k_path_orig_cell( | ||
| structure, | ||
| reference_distance=q_distance.to('1 / angstrom').magnitude) | ||
|
|
||
| if insert_gamma: | ||
| _insert_gamma(bandpath) | ||
|
|
||
| # If input structure was not primitive, the high-symmetry points are not | ||
| # really meaningful. Indicate this by converting to numerical form. | ||
| if bandpath.get('is_supercell'): | ||
| _convert_labels_to_fractions(bandpath, limit=32) | ||
|
|
||
| x_tick_labels = _get_tick_labels(bandpath) | ||
| split_args = {'indices': _get_break_points(bandpath)} | ||
|
|
||
| print( | ||
| 'Computing phonon modes: {n_modes} modes across {n_qpts} q-points' | ||
| .format(n_modes=(data.crystal.n_atoms * 3), | ||
| n_qpts=len(bandpath['explicit_kpoints_rel']))) | ||
|
oerc0122 marked this conversation as resolved.
|
||
| qpts = bandpath['explicit_kpoints_rel'] | ||
|
|
||
| if frequencies_only: | ||
| modes = data.calculate_qpoint_frequencies(qpts, | ||
| reduce_qpts=False, | ||
| **calc_modes_kwargs) | ||
| else: | ||
| modes = data.calculate_qpoint_phonon_modes(qpts, | ||
| reduce_qpts=False, | ||
| **calc_modes_kwargs) | ||
| return modes, x_tick_labels, split_args | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.