def get_z(x, chemical_rules=False): descriptors = ['X', 'average_ionic_radius'] a, b, c = mend_to_name(x[0], x[1], x[2]) # name = a + b + c # conglomerate = [get_pymatgen_descriptor(name, d) for d in descriptors] # means = [np.mean(k) for k in conglomerate] # stds = [np.std(k) for k in conglomerate] # ranges = [np.ptp(k) for k in conglomerate] # z = means + stds + ranges z = [] for d in descriptors[:1]: ab_attrs = [getattr(Element(el), d) for el in (a, b)] c_attrs = get_pymatgen_descriptor(c, d) for attrs_set in [ab_attrs, c_attrs]: z.append(np.mean(attrs_set)) z.append(np.ptp(attrs_set)) z.append(np.std(attrs_set)) z += [Element(a).max_oxidation_state, Element(a).min_oxidation_state] z += [Element(b).max_oxidation_state, Element(b).min_oxidation_state] # Chemical rules rx = np.mean(get_pymatgen_descriptor(c, 'average_ionic_radius')) ra = Element(a).average_ionic_radius rb = Element(b).average_ionic_radius gs_dev = abs(1 - (ra + rx) / (2**0.5 * (rb + rx))) if chemical_rules: z.append(gs_dev) return z
def test_descriptor_ionic_radii(self): ionic_radii = get_pymatgen_descriptor(self.nacl_formula_2, "ionic_radii") self.assertEqual(ionic_radii, [1.16, 1.67]) with self.assertRaises(ValueError): get_pymatgen_descriptor(self.nacl_formula_1, "ionic_radii") ionic_radii = get_pymatgen_descriptor(self.fe2o3_formula_1, "ionic_radii") self.assertEqual(ionic_radii, [0.785, 0.785, 1.26, 1.26, 1.26])
def test_descriptor_ionic_radii(self): ionic_radii = get_pymatgen_descriptor(self.nacl_formula_2, "ionic_radii") self.assertEqual(ionic_radii, [1.16, 1.67]) with self.assertRaises(ValueError): get_pymatgen_descriptor(self.nacl_formula_1, "ionic_radii") ionic_radii = get_pymatgen_descriptor(self.fe2o3_formula_1, "ionic_radii") self.assertEqual(ionic_radii, [0.785, 0.785, 1.26, 1.26, 1.26])
def predict(self, structure): """ Given a structure, returns back the predicted volume. Args: structure (Structure): structure w/unknown volume Returns: a float value of the predicted volume """ if not structure.is_ordered: raise ValueError("VolumePredictor requires ordered structures!") smallest_ratio = None # ratio of observed vs expected bond distance ionic_mix = min( np.std(get_pymatgen_descriptor(structure.composition, 'X')) * self.ionic_factor, 1) for site in structure: el1 = site.specie if el1.atomic_radius: r1 = el1.average_ionic_radius * ionic_mix + \ el1.atomic_radius * ( 1 - ionic_mix) if el1.average_ionic_radius else el1.atomic_radius neighbors = structure.get_neighbors( site, el1.atomic_radius + self.cutoff) for site2, dist in neighbors: el2 = site2.specie if el2.atomic_radius: r2 = el2.average_ionic_radius * ionic_mix + \ el2.atomic_radius * ( 1 - ionic_mix) if el2.average_ionic_radius else el2.atomic_radius expected_dist = float(r1 + r2) if not smallest_ratio or dist / expected_dist \ < smallest_ratio: smallest_ratio = dist / expected_dist else: warnings.warn("VolumePredictor: no atomic radius data " "for {}".format(el2)) else: warnings.warn("VolumePredictor: no atomic radius data for " "{}".format(el1)) if not smallest_ratio: raise ValueError("Could not find any bonds in this material!") volume_factor = (1 / smallest_ratio)**3 return structure.volume * volume_factor
def predict(self, structure): """ Given a structure, returns back the predicted volume. Args: structure (Structure): structure w/unknown volume Returns: a float value of the predicted volume """ if not structure.is_ordered: raise ValueError("VolumePredictor requires ordered structures!") smallest_ratio = None # ratio of observed vs expected bond distance ionic_mix = min(np.std(get_pymatgen_descriptor(structure.composition, "X")) * self.ionic_factor, 1) for site in structure: el1 = site.specie if el1.atomic_radius: r1 = ( el1.average_ionic_radius * ionic_mix + el1.atomic_radius * (1 - ionic_mix) if el1.average_ionic_radius else el1.atomic_radius ) neighbors = structure.get_neighbors(site, el1.atomic_radius + self.cutoff) for site2, dist in neighbors: el2 = site2.specie if el2.atomic_radius: r2 = ( el2.average_ionic_radius * ionic_mix + el2.atomic_radius * (1 - ionic_mix) if el2.average_ionic_radius else el2.atomic_radius ) expected_dist = float(r1 + r2) if not smallest_ratio or dist / expected_dist < smallest_ratio: smallest_ratio = dist / expected_dist else: warnings.warn("VolumePredictor: no atomic radius data " "for {}".format(el2)) else: warnings.warn("VolumePredictor: no atomic radius data for " "{}".format(el1)) if not smallest_ratio: raise ValueError("Could not find any bonds in this material!") volume_factor = (1 / smallest_ratio) ** 3 return structure.volume * volume_factor
def add_pmgdescriptor_column(self, descriptor, stat_function, stat_name): """ Args: descriptor: (str) name of descriptor - must match the name in the source library stat_function: function to approximate the descriptor. For example, numpy.mean, numpy.std, etc. stat_name: (str) name of stat function to append to new descriptor column name Returns: dataframe with appended descriptor column """ try: self.df[descriptor + self.separator + stat_name] = self.df[self.formula_colname]. \ map(lambda x: stat_function(get_pymatgen_descriptor(Composition(x), descriptor))) except ValueError: self.df.loc[descriptor + self.separator + stat_name] = None except AttributeError: raise ValueError('Invalid pymatgen Element attribute!') return self.df
def add_pmgdescriptor_column(self, descriptor, stat_function, stat_name): """ Args: descriptor: (str) name of descriptor - must match the name in the source library stat_function: function to approximate the descriptor. For example, numpy.mean, numpy.std, etc. stat_name: (str) name of stat function to append to new descriptor column name Returns: dataframe with appended descriptor column """ try: self.df[descriptor + self.separator + stat_name] = self.df[self.formula_colname]. \ map(lambda x: stat_function(get_pymatgen_descriptor(Composition(x), descriptor))) except ValueError: self.df.loc[descriptor + self.separator + stat_name] = None except AttributeError: raise ValueError('Invalid pymatgen Element attribute!') return self.df
'Li', 'Be', 'B', 'Na', 'Mg', 'Al', 'Si', 'K', 'Ca', 'Sc', 'Ti', 'V', 'Cr', 'Mn', 'Fe', 'Co', 'Ni', 'Cu', 'Zn', 'Ga', 'Ge', 'As', 'Rb', 'Sr', 'Y', 'Zr', 'Nb', 'Mo', 'Ru', 'Rh', 'Pd', 'Ag', 'Cd', 'In', 'Sn', 'Sb', 'Te', 'Cs', 'Ba', 'La', 'Hf', 'Ta', 'W', 'Re', 'Os', 'Ir', 'Pt', 'Au', 'Hg', 'Tl', 'Pb', 'Bi' ] c_names = ['O3', 'O2N', 'ON2', 'N3', 'O2F', 'OFN', 'O2S'] # Atomic ab_atomic = [Element(name).Z for name in ab_names] c_atomic = list(range(7)) # Mendeleev number ab_mend = [int(Element(name).mendeleev_no) for name in ab_names] c_mend = [ int(np.sum(get_pymatgen_descriptor(anion, 'mendeleev_no'))) for anion in c_names ] # Mendeleev rank ab_mendrank = [sorted(ab_mend).index(i) for i in ab_mend] c_mendrank = [4, 3, 2, 1, 6, 5, 0] # Corrected and relevant perovskite data perovskites = pd.read_csv('unc.csv') # dim = [(0, 51), (0, 51), (0, 6)] # todo: use categorical anions dim = [ab_mend, ab_mend, c_names] # Defining search space with exclusions
def test_descriptor_ionic_radii_from_composition(self): cscl = Composition({Specie("Cs", 1): 1, Specie("Cl", -1): 1}) ionic_radii = get_pymatgen_descriptor(cscl, "ionic_radii") self.assertEqual(ionic_radii, [1.81, 1.67]) ionic_radii_2 = get_pymatgen_descriptor("Cs+1Cl-1", "ionic_radii") self.assertEqual(ionic_radii, ionic_radii_2)
def test_descriptor_ionic_radii_from_composition(self): cscl = Composition({Specie("Cs", 1): 1, Specie("Cl", -1): 1}) ionic_radii = get_pymatgen_descriptor(cscl, "ionic_radii") self.assertEqual(ionic_radii, [1.81, 1.67]) ionic_radii_2 = get_pymatgen_descriptor("Cs+1Cl-1", "ionic_radii") self.assertEqual(ionic_radii, ionic_radii_2)