-
Notifications
You must be signed in to change notification settings - Fork 9
/
utils.py
148 lines (123 loc) · 4.51 KB
/
utils.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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import time
import numpy as np
import ase
import io
import zlib
import tarfile
class CubeWriter():
def __init__(self, filename, atoms, data_shape, origin, comment):
"""
Function to write a cube file. This is a copy of ase.io.cube.write_cube but supports
textIO buffer
filename: str object
File to which output is written.
atoms: Atoms object
Atoms object specifying the atomic configuration.
data_shape: array-like of dimension 1
Shape of the data to come
origin : 3-tuple
Origin of the volumetric data (units: Angstrom)
comment : str, optional (default = None)
Comment for the first line of the cube file.
"""
self.fileobj = open(filename, "w")
self.data_shape = data_shape
self.numbers_written = 0
if comment is None:
comment = 'Cube file from ASE, written on ' + time.strftime('%c')
else:
comment = comment.strip()
self.fileobj.write(comment)
self.fileobj.write('\nOUTER LOOP: X, MIDDLE LOOP: Y, INNER LOOP: Z\n')
if origin is None:
origin = np.zeros(3)
else:
origin = np.asarray(origin) / ase.units.Bohr
self.fileobj.write('{0:5}{1:12.6f}{2:12.6f}{3:12.6f}\n'
.format(len(atoms), *origin))
for i in range(3):
n = data_shape[i]
d = atoms.cell[i] / n / ase.units.Bohr
self.fileobj.write('{0:5}{1:12.6f}{2:12.6f}{3:12.6f}\n'.format(n, *d))
positions = atoms.positions / ase.units.Bohr
numbers = atoms.numbers
for Z, (x, y, z) in zip(numbers, positions):
self.fileobj.write('{0:5}{1:12.6f}{2:12.6f}{3:12.6f}{4:12.6f}\n'
.format(Z, 0.0, x, y, z))
def write(self, data):
for el in data:
self.numbers_written += 1
self.fileobj.write("%e\n" % el)
if self.numbers_written >= np.prod(self.data_shape):
self.fileobj.close()
def write_cube(fileobj, atoms, data=None, origin=None, comment=None):
"""
Function to write a cube file. This is a copy of ase.io.cube.write_cube but supports
textIO buffer
fileobj: file object
File to which output is written.
atoms: Atoms object
Atoms object specifying the atomic configuration.
data : 3dim numpy array, optional (default = None)
Array containing volumetric data as e.g. electronic density
origin : 3-tuple
Origin of the volumetric data (units: Angstrom)
comment : str, optional (default = None)
Comment for the first line of the cube file.
"""
if data is None:
data = np.ones((2, 2, 2))
data = np.asarray(data)
if data.dtype == complex:
data = np.abs(data)
if comment is None:
comment = 'Cube file from ASE, written on ' + time.strftime('%c')
else:
comment = comment.strip()
fileobj.write(comment)
fileobj.write('\nOUTER LOOP: X, MIDDLE LOOP: Y, INNER LOOP: Z\n')
if origin is None:
origin = np.zeros(3)
else:
origin = np.asarray(origin) / ase.units.Bohr
fileobj.write('{0:5}{1:12.6f}{2:12.6f}{3:12.6f}\n'
.format(len(atoms), *origin))
for i in range(3):
n = data.shape[i]
d = atoms.cell[i] / n / ase.units.Bohr
fileobj.write('{0:5}{1:12.6f}{2:12.6f}{3:12.6f}\n'.format(n, *d))
positions = atoms.positions / ase.units.Bohr
numbers = atoms.numbers
for Z, (x, y, z) in zip(numbers, positions):
fileobj.write('{0:5}{1:12.6f}{2:12.6f}{3:12.6f}{4:12.6f}\n'
.format(Z, 0.0, x, y, z))
for el in data.flat:
fileobj.write("%e\n" % el)
def write_cube_to_tar(tar, atoms, cubedata, origin, filename):
"""write_cube_to_tar
Write cube file to tar archive and compress the file using zlib.
Cubedata is expected to be in electrons/A^3 and is converted to
electrons/Bohr^3, which is cube file convention
:param tar:
:param atoms:
:param cubedata:
:param origin:
:param filename:
"""
cbuf = io.StringIO()
write_cube(
cbuf,
atoms,
data=cubedata*(ase.units.Bohr**3),
origin=origin,
comment=filename,
)
cbuf.seek(0)
cube_bytes = cbuf.getvalue().encode()
cbytes = zlib.compress(cube_bytes)
fsize = len(cbytes)
cbuf = io.BytesIO(cbytes)
cbuf.seek(0)
tarinfo = tarfile.TarInfo(name=filename)
tarinfo.size = fsize
tar.addfile(tarinfo, cbuf)