class TestMagpieData(TestCase): def setUp(self): self.data_source = MagpieData() def test_get_property(self): self.assertAlmostEqual(9.012182, self.data_source.get_elemental_property(Element("Be"), "AtomicWeight")) def test_get_oxidation(self): self.assertEqual([-4, 2, 4], self.data_source.get_oxidation_states(Element("C")))
class ValenceOrbitalEnergy(BaseFeaturizer): def __init__(self): self.element_props = {} self.MagpieData = MagpieData() def get_element_props(self,el): try: props = self.element_props[el] except KeyError: subshells = 'spdf' n_elec = {sub:self.MagpieData.get_elemental_property(el,f'N{sub}Valence') for sub in subshells} orbitals = sorted(el.atomic_orbitals.keys())[::-1] #look up valence orbital for subshell orbital_func = lambda x: '{}{}'.format(max([orb[0] for orb in orbitals if orb[1]==x]),x) #get valence orbital energy for subshell energy_func = lambda x: el.atomic_orbitals[orbital_func(x)] props = {x:{'n_elec':n_elec[x],'energy':energy_func(x),'shell':orbital_func(x)[0]} for x in subshells if n_elec[x]>0} self.element_props[el] = props return props def featurize(self,comp): tot_energy = 0 tot_elec = 0 for el in comp.elements: props = self.get_element_props(el) tot_energy += comp[el]*sum([v['energy']*v['n_elec'] for v in props.values()]) tot_elec += comp[el]*sum([v['n_elec'] for v in props.values()]) return [tot_energy/tot_elec] def feature_labels(self): return ['MeanValenceEnergy'] def citations(self): return [ "@article{Ward2016," "archivePrefix = {arXiv}," "arxivId = {1606.09551}," "author = {Ward, Logan and Agrawal, Ankit and Choudhary, Alok and Wolverton, Christopher}," "doi = {10.1038/npjcompumats.2016.28}," "eprint = {1606.09551}," "isbn = {2057-3960}," "issn = {20573960}," "journal = {npj Computational Materials}," "number = {June}," "pages = {1--7}," "title = {{A general-purpose machine learning framework for predicting properties of inorganic materials}}," "volume = {2}," "year = {2016}" "}"]
class Meredig(BaseFeaturizer): """ Class to calculate features as defined in Meredig et. al. Features: Atomic fraction of each of the first 103 elements, in order of atomic number. 17 statistics of elemental properties; Mean atomic weight of constituent elements Mean periodic table row and column number Mean and range of atomic number Mean and range of atomic radius Mean and range of electronegativity Mean number of valence electrons in each orbital Fraction of total valence electrons in each orbital """ def __init__(self): self.data_source = MagpieData() #The labels for statistics on element properties self._element_property_feature_labels = [ "mean AtomicWeight", "mean Column", "mean Row", "range Number", "mean Number", "range AtomicRadius", "mean AtomicRadius", "range Electronegativity", "mean Electronegativity" ] # Initialize stats computer self.pstats = PropertyStats() def featurize(self, comp): """ Get elemental property attributes Args: comp: Pymatgen composition object Returns: all_attributes: Specified property statistics of features """ # First 103 features are element fractions, we can get these from the ElementFraction featurizer element_fraction_features = ElementFraction().featurize(comp) # Next 9 features are statistics on elemental properties elements, fractions = zip(*comp.element_composition.items()) element_property_features = [0] * len(self._element_property_feature_labels) for i,feat in enumerate(self._element_property_feature_labels): stat = feat.split(" ")[0] attr = " ".join(feat.split(" ")[1:]) elem_data = [self.data_source.get_elemental_property(e, attr) for e in elements] element_property_features[i] = self.pstats.calc_stat(elem_data, stat, fractions) # Final 8 features are statistics on valence orbitals, available from the ValenceOrbital featurizer valence_orbital_features = ValenceOrbital(orbitals=("s", "p", "d", "f"), props=("avg", "frac")).featurize(comp) return element_fraction_features+element_property_features+valence_orbital_features def feature_labels(self): # Since we have more features than just element fractions, append 'fraction' to element symbols for clarity element_fraction_features = [e + " fraction" for e in ElementFraction().feature_labels()] valence_orbital_features = ValenceOrbital().feature_labels() return element_fraction_features+self._element_property_feature_labels+valence_orbital_features def citations(self): citation = [ "@article{meredig_agrawal_kirklin_saal_doak_thompson_zhang_choudhary_wolverton_2014, title={Combinatorial " "screening for new materials in unconstrained composition space with machine learning}, " "volume={89}, DOI={10.1103/PhysRevB.89.094104}, number={1}, journal={Physical " "Review B}, author={B. Meredig, A. Agrawal, S. Kirklin, J. E. Saal, J. W. Doak, A. Thompson, " "K. Zhang, A. Choudhary, and C. Wolverton}, year={2014}}"] return citation def implementors(self): return ["Amalie Trewartha"]