Source code for jarvis.core.composition

"""Modules handling chemical composition."""
# from math import gcd
import string
from jarvis.core.specie import Specie
from collections import OrderedDict
from collections import defaultdict
from jarvis.core.utils import gcd
import re
import numpy as np


[docs]class Composition(object): """Generate composition python object.""" def __init__(self, content={}, sort=False): """ Initialize with a dictionary. This class is used in Atoms and related objects. Args: content: dictioary. sort: whether to sort alphabetically. >>> from composition import Composition >>> comp = {"Li": 2, "O": 4} >>> cc = Composition(comp) >>> weight = round(cc.weight,4) >>> print(cc.prototype,cc.formula,cc.reduced_formula,weight) AB2 Li2O4 LiO2 77.8796 """ if sort: content = OrderedDict( sorted(content.items(), key=lambda x: (x[0])) ) self._content = content
[docs] @staticmethod def from_string(value, sort=True): """Generate composition from string.""" re_formula = re.compile(r"([A-Z][a-z]?)([0-9\.]*)") d = defaultdict(float) for elt, amt in re_formula.findall(value): if elt in ["D", "T"]: elt = "H" if amt == "": d[elt] = 1 elif float(amt).is_integer(): d[elt] += int(float(amt)) else: d[elt] += float(amt) comp = Composition(dict(d), sort=sort) return comp
[docs] def reduce(self): """Reduce chemical formula.""" repeat = 0 for specie, count in self._content.items(): if repeat == 0: repeat = count else: repeat = gcd(count, repeat) reduced = {} for specie, count in self._content.items(): reduced[specie] = count // repeat return reduced, repeat
@property def prototype(self): """Get chemical prototypes such as A, AB etc.""" proto = "" all_upper = string.ascii_uppercase reduced, repeat = self.reduce() N = 0 for specie, count in reduced.items(): proto = proto + str(all_upper[N]) + str(round(count, 3)) N = N + 1 return proto.replace("1", "")
[docs] def to_dict(self): """Return dictionary format.""" return self._content
@property def nspecies(self): """Return number of species.""" return len(list(self.to_dict().keys())) @property def search_string(self): """Return JARVIS sorted search string.""" return "-".join(sorted(list(self.to_dict().keys())))
[docs] @classmethod def from_dict(self, d={}): """Load the class from a dictionary.""" return Composition(content=d)
@property def reduced_formula(self): """Get reduced formula.""" form = "" reduced, repeat = self.reduce() X = {} for i, j in reduced.items(): X[i] = Specie(i).X Y = dict(sorted(X.items(), key=lambda item: item[1])) Z = {} for i, j in Y.items(): Z[i] = reduced[i] for specie, count in Z.items(): if float(count).is_integer(): if count == 1: form = form + specie else: form = form + specie + str(int(count)) else: form = form + specie + str(count) return form # .replace("1", "") @property def formula(self): """Get total chemical formula.""" form = "" for specie, count in self._content.items(): if float(count).is_integer(): form = form + str(specie) + str(int(count)) else: form = form + str(specie) + str(count) return form.replace("1", "") @property def atomic_fraction(self): """Get atomic fraction.""" comp_dict = self.to_dict() tot = sum(comp_dict.values()) new_dict = OrderedDict() for i, j in comp_dict.items(): new_dict[i] = j / tot return new_dict @property def atomic_fraction_array(self): """Get atomic fraction array.""" nelements = len(list(Specie()._data.keys())) frac_arr = np.zeros(nelements) fracs = self.atomic_fraction for i, j in fracs.items(): frac_arr[int(Specie(i).Z) - 1] = j return frac_arr @property def weight(self): """Get atomic weight.""" wt = 0.0 for specie, count in self._content.items(): wt = wt + Specie(specie).atomic_mass * count return wt
[docs] def __repr__(self): """Representation of the class.""" return str(self._content)
""" if __name__ == "__main__": c=Composition.from_string('Al2O3Al5Co6O1') print ('Al2O3Al5Co6O1',c.formula, c.reduced_formula) import sys sys.exit() comp = {"Li": 2, "O": 4} cc = Composition(comp) print("dict", cc.to_dict()) x, y = cc.reduce() # print(x, y) proto = cc.prototype print(proto, cc.formula, cc.reduced_formula) """