def test_cns(self): cnv = CoordinationNumber.from_preset('VoronoiNN') self.assertEqual(len(cnv.feature_labels()), 1) self.assertEqual(cnv.feature_labels()[0], 'CN_VoronoiNN') self.assertAlmostEqual(cnv.featurize(self.sc, 0)[0], 6) self.assertAlmostEqual(cnv.featurize(self.cscl, 0)[0], 14) self.assertAlmostEqual(cnv.featurize(self.cscl, 1)[0], 14) self.assertEqual(len(cnv.citations()), 2) cnv = CoordinationNumber(VoronoiNN(), use_weights='sum') self.assertEqual(cnv.feature_labels()[0], 'CN_VoronoiNN') self.assertAlmostEqual(cnv.featurize(self.cscl, 0)[0], 9.2584516) self.assertAlmostEqual(cnv.featurize(self.cscl, 1)[0], 9.2584516) self.assertEqual(len(cnv.citations()), 2) cnv = CoordinationNumber(VoronoiNN(), use_weights='effective') self.assertEqual(cnv.feature_labels()[0], 'CN_VoronoiNN') self.assertAlmostEqual(cnv.featurize(self.cscl, 0)[0], 11.648923254) self.assertAlmostEqual(cnv.featurize(self.cscl, 1)[0], 11.648923254) self.assertEqual(len(cnv.citations()), 2) cnj = CoordinationNumber.from_preset('JmolNN') self.assertEqual(cnj.feature_labels()[0], 'CN_JmolNN') self.assertAlmostEqual(cnj.featurize(self.sc, 0)[0], 0) self.assertAlmostEqual(cnj.featurize(self.cscl, 0)[0], 0) self.assertAlmostEqual(cnj.featurize(self.cscl, 1)[0], 0) self.assertEqual(len(cnj.citations()), 1) jmnn = JmolNN(el_radius_updates={"Al": 1.55, "Cl": 1.7, "Cs": 1.7}) cnj = CoordinationNumber(jmnn) self.assertEqual(cnj.feature_labels()[0], 'CN_JmolNN') self.assertAlmostEqual(cnj.featurize(self.sc, 0)[0], 6) self.assertAlmostEqual(cnj.featurize(self.cscl, 0)[0], 8) self.assertAlmostEqual(cnj.featurize(self.cscl, 1)[0], 8) self.assertEqual(len(cnj.citations()), 1) cnmd = CoordinationNumber.from_preset('MinimumDistanceNN') self.assertEqual(cnmd.feature_labels()[0], 'CN_MinimumDistanceNN') self.assertAlmostEqual(cnmd.featurize(self.sc, 0)[0], 6) self.assertAlmostEqual(cnmd.featurize(self.cscl, 0)[0], 8) self.assertAlmostEqual(cnmd.featurize(self.cscl, 1)[0], 8) self.assertEqual(len(cnmd.citations()), 1) cnmok = CoordinationNumber.from_preset('MinimumOKeeffeNN') self.assertEqual(cnmok.feature_labels()[0], 'CN_MinimumOKeeffeNN') self.assertAlmostEqual(cnmok.featurize(self.sc, 0)[0], 6) self.assertAlmostEqual(cnmok.featurize(self.cscl, 0)[0], 8) self.assertAlmostEqual(cnmok.featurize(self.cscl, 1)[0], 6) self.assertEqual(len(cnmok.citations()), 2) cnmvire = CoordinationNumber.from_preset('MinimumVIRENN') self.assertEqual(cnmvire.feature_labels()[0], 'CN_MinimumVIRENN') self.assertAlmostEqual(cnmvire.featurize(self.sc, 0)[0], 6) self.assertAlmostEqual(cnmvire.featurize(self.cscl, 0)[0], 8) self.assertAlmostEqual(cnmvire.featurize(self.cscl, 1)[0], 14) self.assertEqual(len(cnmvire.citations()), 2) self.assertEqual(len(cnmvire.implementors()), 2) self.assertEqual(cnmvire.implementors()[0], 'Nils E. R. Zimmermann')
def get_fps(structure, cutoff=10.0, processes=8): all_descrs = [] try: coordination_number_ = CoordinationNumber.from_preset('VoronoiNN') voronoi_fps_ = VoronoiFingerprintModified( cutoff=cutoff).featurize_structure(structure) crystal_nn_fingerprint_ = CrystalNNFingerprint.from_preset('cn') op_site_fingerprint_ = OPSiteFingerprint() agni_fingerprints_ = AGNIFingerprints() gaussian_symm_func_fps_ = GaussianSymmFuncModified( ).featurize_structure(structure) pymatgen_data_ = PymatgenData() magpie_data_ = MagpieData() data_list = [[ structure, i, site, coordination_number_, voronoi_fps_, crystal_nn_fingerprint_, op_site_fingerprint_, agni_fingerprints_, gaussian_symm_func_fps_, pymatgen_data_, magpie_data_ ] for i, site in enumerate(structure)] pool = multiprocessing.Pool(processes=processes) all_descrs = np.array(pool.map(get_all_site_descrs, data_list)) except (AttributeError, IndexError) as error: pass return all_descrs
def from_preset(preset, **kwargs): """ Create a SiteStatsFingerprint class according to a preset Args: preset (str) - Name of preset kwargs - Options for SiteStatsFingerprint """ if preset == "CrystalNNFingerprint_cn": return SiteStatsFingerprint( CrystalNNFingerprint.from_preset("cn", cation_anion=False), **kwargs) elif preset == "CrystalNNFingerprint_cn_cation_anion": return SiteStatsFingerprint( CrystalNNFingerprint.from_preset("cn", cation_anion=True), **kwargs) elif preset == "CrystalNNFingerprint_ops": return SiteStatsFingerprint( CrystalNNFingerprint.from_preset("ops", cation_anion=False), **kwargs) elif preset == "CrystalNNFingerprint_ops_cation_anion": return SiteStatsFingerprint( CrystalNNFingerprint.from_preset("ops", cation_anion=True), **kwargs) elif preset == "OPSiteFingerprint": return SiteStatsFingerprint(OPSiteFingerprint(), **kwargs) elif preset == "LocalPropertyDifference_ward-prb-2017": return SiteStatsFingerprint( LocalPropertyDifference.from_preset("ward-prb-2017"), stats=["minimum", "maximum", "range", "mean", "avg_dev"]) elif preset == "CoordinationNumber_ward-prb-2017": return SiteStatsFingerprint( CoordinationNumber(nn=VoronoiNN(weight='area'), use_weights="effective"), stats=["minimum", "maximum", "range", "mean", "avg_dev"]) elif preset == "Composition-dejong2016_AD": return SiteStatsFingerprint( LocalPropertyDifference(properties=[ "Number", "AtomicWeight", "Column", "Row", "CovalentRadius", "Electronegativity" ], signed=False), stats=['holder_mean::%d' % d for d in range(0, 4 + 1)] + ['std_dev'], ) elif preset == "Composition-dejong2016_SD": return SiteStatsFingerprint( LocalPropertyDifference(properties=[ "Number", "AtomicWeight", "Column", "Row", "CovalentRadius", "Electronegativity" ], signed=True), stats=['holder_mean::%d' % d for d in [1, 2, 4]] + ['std_dev'], ) elif preset == "BondLength-dejong2016": return SiteStatsFingerprint( AverageBondLength(VoronoiNN()), stats=['holder_mean::%d' % d for d in range(-4, 4 + 1)] + ['std_dev', 'geom_std_dev']) elif preset == "BondAngle-dejong2016": return SiteStatsFingerprint( AverageBondAngle(VoronoiNN()), stats=['holder_mean::%d' % d for d in range(-4, 4 + 1)] + ['std_dev', 'geom_std_dev']) else: # TODO: Why assume coordination number? Should this just raise an error? - lw # One of the various Coordination Number presets: # MinimumVIRENN, MinimumDistanceNN, JmolNN, VoronoiNN, etc. try: return SiteStatsFingerprint( CoordinationNumber.from_preset(preset), **kwargs) except: pass raise ValueError("Unrecognized preset!")
def structure_to_convmol(structure, properties=ELEMENTAL_PROPERTIES, max_atoms=200, max_features=41, tolerance_distance=0.25): atomic_radii = { 'At': 1.50, 'Bk': 1.70, 'Cm': 1.74, 'Fr': 2.60, 'He': 0.28, 'Kr': 1.16, 'Lr': 1.71, 'Md': 1.94, 'Ne': 0.58, 'No': 1.97, 'Rn': 1.50, 'Xe': 1.40, } distance_matrix = structure.distance_matrix for index, x in np.ndenumerate(distance_matrix): radius_1 = Element(structure._sites[ index[0]].specie).atomic_radius or atomic_radii[str( structure._sites[index[0]].specie)] radius_2 = Element(structure._sites[ index[1]].specie).atomic_radius or atomic_radii[str( structure._sites[index[1]].specie)] max_distance = radius_1 + radius_2 + tolerance_distance if x > max_distance: distance_matrix[index] = 0 else: distance_matrix[index] = 1 np.fill_diagonal(distance_matrix, 1) atom_features = [] for i, site in enumerate(structure._sites): atom_feature_vector = [] for atom_property in properties: min_value = np.nanmin( np.array(list(atom_property.values()), dtype=float)) max_value = np.nanmax( np.array(list(atom_property.values()), dtype=float)) if atom_property[str(Element(site.specie))] is not None: atom_feature_vector.append( (atom_property[str(Element(site.specie))] - min_value) / (max_value - min_value)) else: atom_feature_vector.append(None) voronoi_min = np.array([ 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0 ]) voronoi_max = np.array([ 120.0, 135.0, 11.0, 3.0, 11.0, 12.0, 18.0, 7.0, 17.0, 17.0, 6.0, 2.0, 6.0, 7.0 ]) voronoi_fps = VoronoiFingerprint().featurize(structure, i) i_fold_symmetry_indices = voronoi_fps[8:16] voronoi_stats = (np.array(voronoi_fps[16:]) - voronoi_min) / (voronoi_max - voronoi_min) atom_feature_vector.extend(i_fold_symmetry_indices + voronoi_stats.tolist()) coord_min = np.array([1]) coord_max = np.array([36]) coord_fps = ( (CoordinationNumber.from_preset("MinimumDistanceNN").featurize( structure, i) - coord_min) / (coord_max - coord_min)).tolist() atom_feature_vector.extend(coord_fps) atom_features.append(atom_feature_vector) atom_features = np.array(atom_features, dtype=np.float) if np.isnan(atom_features).any(): raise ValueError('feature vector contains nan value') return (zfill(distance_matrix, max_atoms, max_atoms), zfill(atom_features, max_atoms, max_features), len(structure.sites))