Extraction of cluster geometries from a trajectory
[1]:
from exa.util import isotopes
import exatomic
from exatomic.core.two import compute_atom_two_out_of_core # If we need to compute atom_two out of core (low RAM)
from exatomic.algorithms.neighbors import periodic_nearest_neighbors_by_atom # Only valid for simple cubic periodic cells
from exatomic.base import resource # Helper function to find the path to an example file
[2]:
xyzpath = resource("rh2.traj.xyz")
[3]:
xyz = exatomic.XYZ(xyzpath) # Editor that can parse the XYZ file and build a universe!
[4]:
u = xyz.to_universe() # Parse the XYZ data to a universe
[5]:
u.info() # Current tables
[5]:
size | type | |
---|---|---|
object | ||
METADATA | 48 | - |
WIDGET | 0 | - |
atom | 985706 | exatomic.core.atom.Atom |
frame | 1616 | exatomic.core.frame.Frame |
[6]:
# Add the unit cell dimensions to the frame table of the universe
a = 37.08946302
for i, q in enumerate(("x", "y", "z")):
for j, r in enumerate(("i", "j", "k")):
if i == j:
u.frame[q+r] = a
else:
u.frame[q+r] = 0.0
u.frame["o"+q] = 0.0
u.frame['periodic'] = True
[7]:
len(u) # Number of steps in this trajectory (small for example purposes)
[7]:
101
[8]:
isotopes.Rh.radius # Default Rh (covalent) radius
[8]:
2.3621574999999995
To extract clusters from the trajectory, we don’t need to pre-compute atom_two
[9]:
u.atom.head()
[9]:
symbol | x | y | z | frame | |
---|---|---|---|---|---|
atom | |||||
0 | Rh | 19.3251 | 20.99490 | 12.9253 | 0 |
1 | Rh | 20.8605 | 19.40470 | 17.0475 | 0 |
2 | Cl | 32.7903 | 9.48909 | 27.4356 | 0 |
3 | Cl | 27.2017 | 10.59920 | 26.4768 | 0 |
4 | Cl | 39.1224 | 25.75620 | 13.6518 | 0 |
[10]:
%%time
dct = periodic_nearest_neighbors_by_atom(u, # Universe with all frames from which we want to extract clusters
"Rh", # Source atom from which we will search for neighbors
a, # Cubic cell dimension
# Cluster sizes we want
[0, 1, 2, 3, 4, 8, 12, 16],
# Additional arguments to be passed to the atomic two body calculation
# Note that it is critical to increase dmax (in compute_atom_two)!!!
Rh=2.6, dmax=a/2)
CPU times: user 2min 20s, sys: 2min 35s, total: 4min 56s
Wall time: 5min 20s
[11]:
dct.keys() # 'dct' is a dictionary containing our clustered universes as well as the sorted neighbor list (per frame)
[11]:
dict_keys(['nearest', 0, 1, 2, 3, 4, 8, 12, 16])
[12]:
dct['nearest'].head() # Table of sorted indexes of nearest molecules to "Rh" in each frame
[12]:
frame | idx | two | atom | molecule | |
---|---|---|---|---|---|
0 | 0 | 18 | 421055 | 5186 | 890 |
1 | 0 | 26 | 420722 | 4930 | 879 |
2 | 0 | 30 | 420997 | 5083 | 859 |
3 | 0 | 34 | 420801 | 5090 | 857 |
4 | 0 | 35 | 420834 | 5155 | 881 |
[ ]:
exatomic.UniverseWidget(dct[0]) # Just the analyte
[ ]:
exatomic.UniverseWidget(dct[16]) # View the universe with 16 nearest molecules
If we had wanted to view the entire universe…
[15]:
%time u.compute_atom_two(Rh=2.6) # Compute atom two body data with slightly larger Rh radius
# OR
#%time compute_atom_two_out_of_core("atom_two.hdf", u, a, Rh=2.6) # Writes the two body data to "atom_two.hdf" with keys "frame_{index}/atom_two"
CPU times: user 3.17 s, sys: 281 ms, total: 3.45 s
Wall time: 3.51 s
[16]:
u.memory_usage().sum()/1024**2 # RAM usage (MB)
[16]:
10.53761100769043
[ ]:
exatomic.UniverseWidget(u)
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]: