forked from mosdef-hub/gmso
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathxyz.py
98 lines (81 loc) · 3 KB
/
xyz.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
"""Read and write XYZ files."""
import datetime
import numpy as np
import unyt as u
from gmso.core.atom import Atom
from gmso.core.topology import Topology
from gmso.formats.formats_registry import loads_as, saves_as
@loads_as(".xyz")
def read_xyz(filename):
"""Reader for xyz file format.
Read in an xyz file at the given path and return a Topology object.
Parameters
----------
filename : str
Path to .xyz file that need to be read.
Return
------
top : topology.Topology
Topology object
"""
top = Topology()
with open(filename, "r") as xyz_file:
n_atoms = int(xyz_file.readline())
xyz_file.readline()
coords = np.zeros(shape=(n_atoms, 3)) * u.nanometer
for row, _ in enumerate(coords):
line = xyz_file.readline().split()
if not line:
msg = (
"Incorrect number of lines in input file. Based on the "
"number in the first line of the file, {} rows of atoms "
"were expected, but at least one fewer was found."
)
raise ValueError(msg.format(n_atoms))
tmp = np.array(line[1:4], dtype=float) * u.angstrom
coords[row] = tmp.in_units(u.nanometer)
site = Atom(name=line[0], position=coords[row])
top.add_site(site)
top.update_topology()
# Verify we have read the last line by ensuring the next line in blank
line = xyz_file.readline().split()
if line:
msg = (
"Incorrect number of lines in input file. Based on the "
"number in the first line of the file, {} rows of atoms "
"were expected, but at least one more was found."
)
raise ValueError(msg.format(n_atoms))
return top
@saves_as(".xyz")
def write_xyz(top, filename):
"""Writer for xyz file format.
Write a Topology object to an xyz file at the given path.
Parameters
----------
top : topology.Topology
Topology object that needs to be written out.
filename : str
Path to file location.
"""
with open(filename, "w") as out_file:
out_file.write("{:d}\n".format(top.n_sites))
out_file.write(
"{} {} written by topology at {}\n".format(
top.name, filename, str(datetime.datetime.now())
)
)
out_file.write(_prepare_particles(top))
def _prepare_particles(top: Topology) -> str:
atom_info = str()
for _, site in enumerate(top.sites):
# TODO: Better handling of element guessing and site naming
if site.element is not None:
tmp_name = site.element.symbol
else:
tmp_name = "X"
x = site.position[0].in_units(u.angstrom).value
y = site.position[1].in_units(u.angstrom).value
z = site.position[2].in_units(u.angstrom).value
atom_info = atom_info + f"{tmp_name} {x:8.3f} {y:8.3f} {z:8.3f}\n"
return atom_info