def en_difference_active(self, atoms=None): """Returns a list of electronegativity metrics, squared and summed over adsorbate bonds including those with the surface. Parameters ---------- atoms : object ASE Atoms object. Returns ---------- features : list If None was passed, the elements are strings, naming the feature. """ labels = ['dist_' + s + '_active' for s in electronegativities] if atoms is None: return labels cm = atoms.connectivity ads = atoms.subsets['ads_atoms'] site = atoms.subsets['site_atoms'] active = ads + site bonds = cm[ads, :][:, active] active_numbers = atoms.numbers[active] ads_numbers = atoms.numbers[ads] en_active = list_mendeleev_params(active_numbers, electronegativities) en_ads = list_mendeleev_params(ads_numbers, electronegativities) delta_en = (en_ads[:, np.newaxis, :] - en_active[np.newaxis, :, :]) ** 2 en_result = list(np.einsum("ij,ijk->k", bonds, delta_en)) assert len(en_result) == len(labels) return en_result
def en_difference_chemi(self, atoms=None): """Returns a list of electronegativity metrics, squared and summed over adsorbate-site bonds. Parameters ---------- atoms : object ASE Atoms object. Returns ---------- features : list If None was passed, the elements are strings, naming the feature. """ labels = ['dist_' + s + '_chemi' for s in electronegativities] if atoms is None: return labels cm = atoms.connectivity chemi = atoms.subsets['chemisorbed_atoms'] site = atoms.subsets['site_atoms'] bonds = cm[chemi, :][:, site] chemi_numbers = atoms.numbers[chemi] site_numbers = atoms.numbers[site] en_chemi = list_mendeleev_params(chemi_numbers, electronegativities) en_site = list_mendeleev_params(site_numbers, electronegativities) delta_en = (en_chemi[:, np.newaxis, :] - en_site[np.newaxis, :, :]) ** 2 en_result = list(np.einsum("ij,ijk->k", bonds, delta_en)) assert len(en_result) == len(labels) return en_result
def term(self, atoms=None): """Return a fingerprint vector with propeties averaged over the termination atoms. Parameters ---------- atoms : object """ labels = make_labels(self.slab_params, '', '_term') labels.append('ground_state_magmom_term') if atoms is None: return labels else: if ('key_value_pairs' in atoms.info and 'term' in atoms.info['key_value_pairs']): term = atoms.info['key_value_pairs']['term'] numbers = [atomic_numbers[s] for s in string2symbols(term)] elif 'termination_atoms' in atoms.subsets: term = atoms.subsets['termination_atoms'] numbers = atoms.numbers[term] else: raise NotImplementedError("termination fingerprint.") dat = list_mendeleev_params(numbers, params=self.slab_params) result = list(np.nanmean(dat, axis=0)) result += [np.nanmean([gs_magmom[z] for z in numbers])] check_labels(labels, result, atoms) return result
def mean_surf_ligands(self, atoms=None): """Function that takes an atoms objects and returns a fingerprint vector containing the count of nearest neighbors and properties of the nearest neighbors. Parameters ---------- atoms : object ASE Atoms object. Returns ---------- features : list If None was passed, the elements are strings, naming the feature. """ labels = ['nn_surf_ligands', 'identnn_surf_ligands'] labels += make_labels(self.slab_params, '', '_surf_ligands') labels.append('ground_state_magmom_surf_ligands') if atoms is None: return labels else: ligand_atoms = atoms.subsets['ligand_atoms'] numbers = atoms.numbers[ligand_atoms] # Import CatLearn data on that element. dat = list_mendeleev_params(numbers, params=self.slab_params) result = list(np.nanmean(dat, axis=0)) result += [np.nanmean([gs_magmom[z] for z in numbers])] # Append count of ligand atoms. result = [len(ligand_atoms), len(np.unique(numbers))] + result check_labels(labels, result, atoms) return result
def ads_av(self, atoms=None): """Function that takes an atoms objects and returns a fingerprint vector with averages of the atomic properties of the adsorbate. Parameters ---------- atoms : object ASE Atoms object. Returns ---------- features : list If None was passed, the elements are strings, naming the feature. """ ads_params = default_params + ['econf', 'ionenergies'] labels = make_labels(ads_params, '', '_ads_av') labels.append('ground_state_magmom_ads_av') if atoms is None: return labels else: numbers = [atoms[j].number for j in atoms.subsets['ads_atoms']] dat = list_mendeleev_params(numbers, params=ads_params) result = list(np.nanmean(dat, axis=0)) result += [np.nanmean([gs_magmom[z] for z in numbers])] check_labels(labels, result, atoms) return result
def mean_chemisorbed_atoms(self, atoms=None): """Function that takes an atoms objects and returns a fingerprint vector containing properties of the closest add atom to a surface metal atom. Parameters ---------- atoms : object ASE Atoms object. Returns ---------- features : list If None was passed, the elements are strings, naming the feature. """ extra_ads_params = ['atomic_radius', 'heat_of_formation', 'oxistates', 'block', 'econf', 'ionenergies'] labels = make_labels(default_params + extra_ads_params, '', '_ads1') labels.append('ground_state_magmom_ads1') if atoms is None: return labels else: # Get atomic number of alpha adsorbate atom. chemisorbed_atoms = atoms.subsets['chemisorbed_atoms'] numbers = atoms.numbers[chemisorbed_atoms] # Import CatLearn data on that element. dat = list_mendeleev_params(numbers, params=default_params + extra_ads_params) result = list(np.nanmean(dat, axis=0)) result += [np.nanmean([gs_magmom[z] for z in numbers])] check_labels(labels, result, atoms) return result
def sum_site(self, atoms=None): """Function that takes an atoms objects and returns a fingerprint vector with properties summed over the surface metal atoms closest to an add atom. Parameters ---------- atoms : object ASE Atoms object. Returns ---------- features : list If None was passed, the elements are strings, naming the feature. """ labels = make_labels(self.slab_params, '', '_site_sum') labels.append('ground_state_magmom_site_sum') if atoms is None: return labels else: numbers = [atoms[j].number for j in atoms.subsets['site_atoms']] dat = list_mendeleev_params(numbers, params=self.slab_params) result = list(np.nansum(dat, axis=0)) result += [np.nansum([gs_magmom[z] for z in numbers])] check_labels(labels, result, atoms) return result
def bulk(self, atoms=None): """Return a fingerprint vector with propeties averaged over the bulk atoms. Parameters ---------- atoms : object ASE Atoms object. Returns ---------- features : list If None was passed, the elements are strings, naming the feature. """ labels = make_labels(self.slab_params, '', '_bulk') labels.append('ground_state_magmom_bulk') if atoms is None: return labels else: if ('key_value_pairs' in atoms.info and 'bulk' in atoms.info['key_value_pairs']): bulk = atoms.info['key_value_pairs']['bulk'] numbers = [atomic_numbers[s] for s in string2symbols(bulk)] elif 'bulk_atoms' in atoms.subsets: bulk = atoms.subsets['bulk_atoms'] numbers = atoms.numbers[bulk] else: raise NotImplementedError("bulk fingerprint.") dat = list_mendeleev_params(numbers, params=self.slab_params) result = list(np.nanmean(dat, axis=0)) result += [np.nanmean([gs_magmom[z] for z in numbers])] check_labels(labels, result, atoms) return result
def bulk_summation(self, atoms=None): """Return a fingerprint vector with propeties of the element name saved in the atoms.info['key_value_pairs']['bulk']""" if atoms is None: return ['atomic_number_sum', 'atomic_volume_sum', 'boiling_point_sum', 'density_sum', 'dipole_polarizability_sum', 'electron_affinity_sum', 'group_id_sum', 'lattice_constant_sum', 'melting_point_sum', 'period_sum', 'vdw_radius_sum', 'covalent_radius_cordero_sum', 'en_allen_sum', 'atomic_weight_sum', 'c6_sum', 'c6_gb_sum', 'en_allred-rochow_sum', 'en_cottrell-sutton_sum', 'en_gordy_sum', 'en_martynov-batsanov_sum', 'en_mulliken_sum', 'en_nagle_sum', 'en_ghosh_sum', 'gas_basicity_sum', 'metallic_radius_sum', 'atomic_radius_sum', 'heat_of_formation_sum', 'dft_sum_modulus_sum', 'dft_rhodensity_sum', 'en_pauling_sum', 'dbcenter_sum', 'dbfilling_sum', 'dbwidth_sum', 'dbskew_sum', 'dbkurtosis_sum', 'sblock_sum', 'pblock_sum', 'dblock_sum', 'fblock_sum', 'ne_outer_sum', 'ne_s_sum', 'ne_p_sum', 'ne_d_sum', 'ne_f_sum', 'ionenergy_sum', 'ground_state_magmom_sum'] else: numbers = atoms.get_atomic_numbers() dat = list_mendeleev_params(numbers, params=default_params + self.extra_params) result = list(np.nansum(dat, axis=0)) result += [np.nansum([gs_magmom[z] for z in numbers])] return result
def get_autocorrelation(self, atoms): """Return the autocorrelation fingerprint for a molecule.""" connectivity = catlearn_neighborlist(atoms) G = nx.Graph(connectivity) distance_matrix = nx.floyd_warshall_numpy(G) Bm = np.zeros(distance_matrix.shape) n = len(self.parameters) W = list_mendeleev_params(atoms.numbers, self.parameters).T fingerprint = np.zeros(n * (self.dstar + 1)) for dd in range(self.dstar + 1): B = Bm.copy() B[distance_matrix == dd] = 1 AC = np.dot(np.dot(W, B), W.T).diagonal() fingerprint[n * dd:n * (dd + 1)] = AC return fingerprint
def en_difference_ads(self, atoms=None): """Returns a list of electronegativity metrics, squared and summed over bonds within the adsorbate atoms. Parameters ---------- atoms : object """ labels = ['dist_' + s + '_ads' for s in electronegativities] if atoms is None: return labels cm = atoms.connectivity ads = atoms.subsets['ads_atoms'] bonds = cm[ads, :][:, ads] ads_numbers = atoms.numbers[ads] en_ads = list_mendeleev_params(ads_numbers, electronegativities) delta_en = (en_ads[:, np.newaxis, :] - en_ads[np.newaxis, :, :])**2 en_result = list(np.einsum("ij,ijk->k", bonds, delta_en)) assert len(en_result) == len(labels) return en_result
def median_site(self, atoms=None): """Function that takes an atoms objects and returns a fingerprint vector with properties averaged over the surface metal atoms closest to an add atom. Parameters ---------- atoms : object """ labels = make_labels(self.slab_params, '', '_site_med') labels.append('ground_state_magmom_site_med') if atoms is None: return labels else: numbers = [atoms[j].number for j in atoms.subsets['site_atoms']] dat = list_mendeleev_params(numbers, params=self.slab_params) result = list(np.nanmedian(dat, axis=0)) result += [np.nanmedian([gs_magmom[z] for z in numbers])] check_labels(labels, result, atoms) return result
def conv_bulk(self, atoms=None): """Return a fingerprint vector with propeties convoluted over the bulk atoms. Parameters ---------- atoms : object A single atoms object. """ labels = [ 'atomic_number_bulk_conv_0', 'atomic_volume_bulk_conv_0', 'boiling_point_bulk_conv_0', 'density_bulk_conv_0', 'dipole_polarizability_bulk_conv_0', 'electron_affinity_bulk_conv_0', 'group_id_bulk_conv_0', 'lattice_constant_bulk_conv_0', 'melting_point_bulk_conv_0', 'period_bulk_conv_0', 'vdw_radius_bulk_conv_0', 'covalent_radius_cordero_bulk_conv_0', 'en_allen_bulk_conv_0', 'atomic_weight_bulk_conv_0', 'atomic_radius_bulk_conv_0', 'heat_of_formation_bulk_conv_0', 'dft_bulk_modulus_bulk_conv_0', 'dft_rhodensity_bulk_conv_0', 'dbcenter_bulk_conv_0', 'dbfilling_bulk_conv_0', 'dbwidth_bulk_conv_0', 'dbskew_bulk_conv_0', 'dbkurtosis_bulk_conv_0', 'oxi_min_bulk_conv_0', 'oxi_med_bulk_conv_0', 'oxi_max_bulk_conv_0', 'sblock_bulk_conv_0', 'pblock_bulk_conv_0', 'dblock_bulk_conv_0', 'fblock_bulk_conv_0', 'ne_outer_bulk_conv_0', 'ne_s_bulk_conv_0', 'ne_p_bulk_conv_0', 'ne_d_bulk_conv_0', 'ne_f_bulk_conv_0', 'ionenergy_bulk_conv_0', 'ground_state_magmom_bulk_conv_0', 'atomic_number_bulk_conv_1', 'atomic_volume_bulk_conv_1', 'boiling_point_bulk_conv_1', 'density_bulk_conv_1', 'dipole_polarizability_bulk_conv_1', 'electron_affinity_bulk_conv_1', 'group_id_bulk_conv_1', 'lattice_constant_bulk_conv_1', 'melting_point_bulk_conv_1', 'period_bulk_conv_1', 'vdw_radius_bulk_conv_1', 'covalent_radius_cordero_bulk_conv_1', 'en_allen_bulk_conv_1', 'atomic_weight_bulk_conv_1', 'atomic_radius_bulk_conv_1', 'heat_of_formation_bulk_conv_1', 'dft_bulk_modulus_bulk_conv_1', 'dft_rhodensity_bulk_conv_1', 'dbcenter_bulk_conv_1', 'dbfilling_bulk_conv_1', 'dbwidth_bulk_conv_1', 'dbskew_bulk_conv_1', 'dbkurtosis_bulk_conv_1', 'oxi_min_bulk_conv_1', 'oxi_med_bulk_conv_1', 'oxi_max_bulk_conv_1', 'sblock_bulk_conv_1', 'pblock_bulk_conv_1', 'dblock_bulk_conv_1', 'fblock_bulk_conv_1', 'ne_outer_bulk_conv_1', 'ne_s_bulk_conv_1', 'ne_p_bulk_conv_1', 'ne_d_bulk_conv_1', 'ne_f_bulk_conv_1', 'ionenergy_bulk_conv_1', 'ground_state_magmom_bulk_conv_1' ] if atoms is None: return labels if 'bulk_atoms' in atoms.subsets: bulk = atoms.subsets['bulk_atoms'] numbers = atoms.numbers[bulk] connectivity = atoms.connectivity[bulk] else: raise NotImplementedError("bulk convoluted fingerprint.") slab_numbers = atoms.numbers dat_b = list_mendeleev_params(numbers, params=self.slab_params) dat = list_mendeleev_params(slab_numbers, params=self.slab_params) result = list(np.sqrt(np.sum(dat_b * dat_b, axis=0)) / len(bulk)) result += [ np.sqrt(np.sum([gs_magmom[z]**2 for z in numbers])) / len(bulk) ] for i in range(dat.shape[1]): result += [ np.sqrt( np.sum(dat[:, i][:len(connectivity)].reshape( len(connectivity), 1) * (dat[:, i] * connectivity))) / len(bulk) ] gsm = np.array([gs_magmom[z] for z in atoms.numbers]) result += [ np.sqrt( np.sum(gsm[:len(connectivity)].reshape(len(connectivity), 1) * (gsm * connectivity))) / len(bulk) ] check_length(labels, result, atoms) return result