-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Gaurav S Deshmukh
committed
Sep 15, 2023
1 parent
97bc2a8
commit 9bd23b1
Showing
3 changed files
with
274 additions
and
4 deletions.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| 0, 0 | ||
| 22, 1.50 | ||
| 23, 1.06 | ||
| 24, 0.16 | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,145 @@ | ||
| """Utility functions.""" | ||
|
|
||
| from copy import deepcopy | ||
|
|
||
| import numpy as np | ||
| import torch | ||
|
|
||
| from featurizers import ( | ||
| list_of_node_featurizers, | ||
| list_of_edge_featurizers, | ||
| OneHotEncoder | ||
| ) | ||
| from graphs import AtomsGraph | ||
|
|
||
| def partition_structure(atoms, n_partitions, z_cutoffs): | ||
| """Partition atomic structue into bulk, surface, and/or adsorbates. | ||
| Parameters | ||
| ---------- | ||
| atoms: ase.Atoms object | ||
| The structure to be partitioned | ||
| n_partitions: int | ||
| Number of partitions | ||
| z_cutoffs: list or np.ndarray | ||
| List of z-coordinate cutoffs. xy planes are placed at the specified | ||
| cutoffs to partition atoms above and below them. The length of z-cutoffs | ||
| should be equal to one less than the number of partitions. | ||
| """ | ||
| # Check if length of z_cutoffs is equal to n_paritions | ||
| if len(z_cutoffs) != n_partitions - 1: | ||
| raise ValueError("The length of z_cutoffs must be equal to\ | ||
| one less than the number of partitions") | ||
|
|
||
| # Add 0 and infinity to cutoffs | ||
| z_cutoffs = np.insert(z_cutoffs, 0, 0) | ||
| z_cutoffs = np.insert(z_cutoffs, len(z_cutoffs), np.inf) | ||
|
|
||
| # Get positions | ||
| pos = atoms.get_positions() | ||
|
|
||
| # Iterate over number of partitions | ||
| part_atoms = [] | ||
| for i in range(n_partitions): | ||
| part_idx = np.argwhere( | ||
| (pos[:, -1] >= z_cutoffs[i]) & (pos[:, -1] < z_cutoffs[i+1]) | ||
| ).flatten().tolist() | ||
| part_atoms.append(part_idx) | ||
|
|
||
| return part_atoms | ||
|
|
||
| def featurize_atoms( | ||
| atoms, | ||
| select_idx, | ||
| node_features, | ||
| edge_features, | ||
| max_atoms=50, | ||
| encoder=OneHotEncoder() | ||
| ): | ||
| """Featurize atoms and bonds with the chosen featurizers. | ||
| Parameters | ||
| ---------- | ||
| atoms: ase.Atoms objet | ||
| Atoms object containing the whole structure | ||
| select_idx: list | ||
| List of indices for atoms to featurize. Typically, this will be provided | ||
| by the partition_structure function | ||
| node_features: list or np.ndarray | ||
| Names of node featurizers to use (current options: atomic_number, dband | ||
| center, valence electrons, coordination, reactivity). The "reactivity" | ||
| featurizer uses valence electrons for adsorbates (atomic number < 21) and | ||
| d-band center for larger transition metal atoms (atomic number >= 21). | ||
| edge_features: list or np.ndarray | ||
| Names of edge featurizers to use (current options: bulk_bond_distance, | ||
| surface_bond_distance, adsorbate_bond_distance). All of these encode | ||
| bond distance using a one-hot encoder, but the bounds for each vary. | ||
| max_atoms: int (default = 50) | ||
| Maximum number of allowed atoms. If the number of atoms in the graph are | ||
| fewer than this number, the graph is padded with empty nodes. This is | ||
| required to make the sizes of the node feature tensors consistent across | ||
| structures. | ||
| encoder: encoder object from featurizers.py | ||
| Currently only the OneHotEncoder is supported | ||
| Returns | ||
| ------- | ||
| dict | ||
| Dictionary with keys "node_tensor", "edge_tensor", and "edge_indices" and | ||
| corresponding tensors as values. | ||
| """ | ||
| # Create graph | ||
| atoms_graph = AtomsGraph(atoms=atoms, select_idx=select_idx, max_atoms=max_atoms) | ||
|
|
||
| # Collect node featurizers | ||
| node_feats = [] | ||
| node_intervals = [] | ||
| for node_featurizer in list_of_node_featurizers: | ||
| if node_featurizer.name() in node_features: | ||
| nf = node_featurizer(deepcopy(encoder)) | ||
| node_intervals.append(nf.n_intervals) | ||
| node_feats.append(nf) | ||
|
|
||
| # Collect edge featurizers | ||
| edge_feats = [] | ||
| edge_intervals = [] | ||
| for edge_featurizer in list_of_edge_featurizers: | ||
| if edge_featurizer.name() in edge_features: | ||
| ef = edge_featurizer(deepcopy(encoder)) | ||
| edge_intervals.append(ef.n_intervals) | ||
| edge_feats.append(ef) | ||
|
|
||
| # Store node matrices from each feaurizer | ||
| node_mats = [] | ||
| for nf in node_feats: | ||
| nf.featurize_graph(atoms_graph) | ||
| node_mats.append(nf.feat_tensor) | ||
| # Stack node mats to create node tensor | ||
| node_tensor = torch.hstack(node_mats) | ||
|
|
||
| # Store edge matrices from each featurizer | ||
| edge_mats = [] | ||
| for ef in edge_feats: | ||
| ef.featurize_graph(atoms_graph) | ||
| edge_mats.append(ef.feat_tensor) | ||
| # Stack edge mats to create edge tensor | ||
| edge_tensor = torch.hstack(edge_mats) | ||
|
|
||
| # Store edge indices | ||
| edge_indices = ef.edge_indices | ||
|
|
||
| return {"node_tensor": node_tensor, "edge_tensor": edge_tensor, | ||
| "edge_indices": edge_indices} | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| from ase.io import read | ||
| atoms = read("CONTCAR") | ||
|
|
||
| part_atoms = partition_structure(atoms, 3, z_cutoffs=[15, 23.5]) | ||
| print(part_atoms) | ||
|
|
||
| feat_dict = featurize_atoms(atoms, part_atoms[0], ["atomic_number", "dband_center"], | ||
| ["bulk_bond_distance"], max_atoms=34) | ||
| print(feat_dict) | ||
|
|