-
Notifications
You must be signed in to change notification settings - Fork 874
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
Added methods to compute and compare DOS fingerprints #2772
Merged
janosh
merged 35 commits into
materialsproject:master
from
naik-aakash:dos_fingerprinting
Dec 24, 2022
Merged
Changes from 16 commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
177a7a9
added dos_fingerprint and similarity index methods
naik-aakash e9669d1
Added test cases and reformatted and cleaned code
naik-aakash 6a52d42
added binwidth ,renamed states to densities in fp obj,updated tests
naik-aakash 04b4ec7
Merge branch 'materialsproject:master' into dos_fingerprinting
naik-aakash 876eefe
remove redundant comment
naik-aakash b7b2296
Merge branch 'dos_fingerprinting' of github.com:naik-aakash/pymatgen …
naik-aakash e5e1c10
Merge branch 'materialsproject:master' into dos_fingerprinting
naik-aakash dcd37ff
added source link
naik-aakash 4f5752c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 1bc772f
fix liniting error
naik-aakash 2a4c76f
Merge branch 'dos_fingerprinting' of github.com:naik-aakash/pymatgen …
naik-aakash 0ee33dd
fix line length linting error
naik-aakash d5468ef
fix line lenghts
naik-aakash 6d68324
changed get_dos_fp_similarity and fp_to_dict methods to static
naik-aakash cf25f28
fixed typo in doc string
naik-aakash eb8cfa4
fixed doc string suggestion
naik-aakash ff7c271
Updated doc strings based on suggestion, added type annotation to the…
naik-aakash 1882916
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 3c476b7
Merge branch 'materialsproject:master' into dos_fingerprinting
naik-aakash 7b1fcee
mypy fixes
naik-aakash b064ac9
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] a1a44e8
fix flake8
naik-aakash 433e5c1
mypy error fix
naik-aakash cb9484f
mypy error fix
naik-aakash f27e5fc
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 746c12a
Delete Test.py
naik-aakash a1f21c2
simplified dict updating, added missing type annotations
naik-aakash a681b70
mypy error fixes
naik-aakash 6445f42
NamedTuple return type fixed
naik-aakash d0cfa20
Merge branch 'materialsproject:master' into dos_fingerprinting
naik-aakash 4b1417e
Merge branch 'materialsproject:master' into dos_fingerprinting
naik-aakash c589945
small clean up
janosh 1c2dbc4
document get_dos_fp() and get_dos_fp_similarity() raise conditions in…
janosh a8216c7
add types for fp1,fp2 and update doc str
janosh 8309b1b
update exception tests
janosh 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 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 |
---|---|---|
|
@@ -9,6 +9,7 @@ | |
|
||
import functools | ||
import warnings | ||
from collections import namedtuple | ||
from typing import Mapping | ||
|
||
import numpy as np | ||
|
@@ -1165,6 +1166,150 @@ def get_upper_band_edge( | |
upper_band_edge = energies[np.argmax(densities)] | ||
return upper_band_edge | ||
|
||
def get_dos_fp(self, type="summed_pdos", binning=True, min_e=None, max_e=None, nbins=256, normalize=True): | ||
""" | ||
Generates the DOS fingerprint based on work of | ||
F. Knoop, T. A. r Purcell, M. Scheffler, C. Carbogno, J. Open Source Softw. 2020, 5, 2671. | ||
Source - https://gitlab.com/vibes-developers/vibes/-/tree/master/vibes/materials_fp | ||
Copyright (c) 2020 Florian Knoop, Thomas A.R.Purcell, Matthias Scheffler, Christian Carbogno | ||
|
||
|
||
Args: | ||
type (str): Specify fingerprint type needed can accept 's/p/d/f/summed_pdos/tdos' | ||
janosh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
min_e (float): The minimum mode energy to include in the fingerprint | ||
max_e (float): The maximum mode energy to include in the fingerprint | ||
nbins (int): Number of bins to be used in the fingerprint | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we rename this to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done 😃 |
||
normalize (bool): If true, normalizes the area under fp to equal to 1 | ||
|
||
Returns: | ||
Fingerprint(namedtuple) : The electronic density of states fingerprint | ||
of format (energies, densities, type, nbins) | ||
""" | ||
fp_tup = namedtuple("fingerprint", "energies densities type nbins binwidth") | ||
energies = self.energies - self.efermi | ||
|
||
if max_e is None: | ||
max_e = np.max(energies) | ||
|
||
if min_e is None: | ||
min_e = np.min(energies) | ||
|
||
pdos_obj = self.get_spd_dos() | ||
|
||
pdos = {} | ||
for k, _v in pdos_obj.items(): | ||
naik-aakash marked this conversation as resolved.
Show resolved
Hide resolved
|
||
dens = pdos_obj[k].get_densities() | ||
naik-aakash marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
pdos.update({k.name: dens}) | ||
naik-aakash marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
sum_pdos_array = [] | ||
for dos in pdos.values(): | ||
sum_pdos_array.append(np.array(dos)) | ||
|
||
pdos.update({"summed_pdos": np.sum(sum_pdos_array, axis=0)}) | ||
pdos.update({"tdos": self.get_densities()}) | ||
naik-aakash marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
try: | ||
|
||
densities = pdos[type] | ||
if len(energies) < nbins: | ||
inds = np.where((energies >= min_e) & (energies <= max_e)) | ||
return fp_tup(energies[inds], densities[inds], type, len(energies), np.diff(energies)[0]) | ||
|
||
if binning: | ||
ener_bounds = np.linspace(min_e, max_e, nbins + 1) | ||
ener = ener_bounds[:-1] + (ener_bounds[1] - ener_bounds[0]) / 2.0 | ||
bin_width = np.diff(ener)[0] | ||
else: | ||
ener_bounds = np.array(energies) | ||
ener = np.append(energies, [energies[-1] + np.abs(energies[-1]) / 10]) | ||
nbins = len(energies) | ||
bin_width = np.diff(energies)[0] | ||
|
||
dos_rebin = np.zeros(ener.shape) | ||
|
||
for ii, e1, e2 in zip(range(len(ener)), ener_bounds[0:-1], ener_bounds[1:]): | ||
inds = np.where((energies >= e1) & (energies < e2))[0] | ||
dos_rebin[ii] = np.sum(densities[inds]) | ||
if normalize: # scale dos bins to make area under histogram equal 1 | ||
area = np.sum(dos_rebin * bin_width) | ||
dos_rebin_sc = dos_rebin / area | ||
else: | ||
dos_rebin_sc = dos_rebin | ||
|
||
return fp_tup(np.array([ener]), dos_rebin_sc, type, nbins, bin_width) | ||
|
||
except KeyError: | ||
raise ValueError( | ||
"Please recheck type requested, either the orbital projections unavailable in input dos or " | ||
"some there exist some mistake in the spelling." | ||
) | ||
|
||
@staticmethod | ||
def fp_to_dict(fp): | ||
naik-aakash marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"""Converts a fingerprint into a dictionary | ||
|
||
Args: | ||
fp: The DOS fingerprint to be converted into a dictionary | ||
|
||
Returns: | ||
dict: A dict of the fingerprint Keys=type, Values=np.ndarray(energies, states) | ||
""" | ||
fp_dict = {} | ||
fp_dict[fp[2]] = np.array([fp[0], fp[1]]).T | ||
|
||
return fp_dict | ||
|
||
@staticmethod | ||
def get_dos_fp_similarity(fp1, fp2, col=1, pt="All", normalize=False, tanimoto=False): | ||
"""Calculates the similarity index (dot product) of two fingerprints | ||
|
||
Args: | ||
fp1 (get_dos_fp): The 1st dos fingerprint | ||
fp2 (get_dos_fp): The 2nd dos fingerprint | ||
col (int): The item in the fingerprints to take the dot product of (0=Energies 1=Densities) | ||
pt (int or 'All') : The index of the point that the dot product is to be taken | ||
normalize (bool): If True normalize the scalar product to 1 | ||
tanimoto (bool): If True will compute tanimoto index | ||
|
||
Returns: | ||
Similarity index (float): The value of dot product | ||
""" | ||
if not isinstance(fp1, dict): | ||
fp1_dict = CompleteDos.fp_to_dict(fp1) | ||
else: | ||
fp1_dict = fp1 | ||
|
||
if not isinstance(fp2, dict): | ||
fp2_dict = CompleteDos.fp_to_dict(fp2) | ||
else: | ||
fp2_dict = fp2 | ||
|
||
if pt == "All": | ||
vec1 = np.array([pt[col] for pt in fp1_dict.values()]).flatten() | ||
vec2 = np.array([pt[col] for pt in fp2_dict.values()]).flatten() | ||
else: | ||
vec1 = fp1_dict[fp1[2][pt]][col] | ||
vec2 = fp2_dict[fp2[2][pt]][col] | ||
|
||
if not normalize and tanimoto: | ||
rescale = np.linalg.norm(vec1) ** 2 + np.linalg.norm(vec2) ** 2 - np.dot(vec1, vec2) | ||
return np.dot(vec1, vec2) / rescale | ||
|
||
elif not tanimoto and normalize: | ||
rescale = np.linalg.norm(vec1) * np.linalg.norm(vec2) | ||
return np.dot(vec1, vec2) / rescale | ||
|
||
elif not tanimoto and not normalize: | ||
rescale = 1.0 | ||
return np.dot(vec1, vec2) / rescale | ||
|
||
else: | ||
raise ValueError( | ||
"Cannot compute similarity index, Please set either one of normalize/tanimoto arg to true " | ||
"or set both to false" | ||
) | ||
|
||
@classmethod | ||
def from_dict(cls, d) -> CompleteDos: | ||
""" | ||
|
This file contains 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
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be good to add type annotations here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the suggestions , I have made the requested changes.