fennol.utils.io

  1import time
  2import numpy as np
  3
  4
  5def xyz_reader(
  6    filename,
  7    has_comment_line=False,
  8    indexed=False,
  9    start=1,
 10    stop=-1,
 11    step=1,
 12    max_frames=None,
 13    stream=False,
 14    interval=2.0,
 15    sleep=time.sleep,
 16):
 17    if stop > 0 and start > stop:
 18        return
 19    pf = open(filename, "r")
 20    inside_frame = False
 21    nat_read = False
 22    iframe = 0
 23    stride = step
 24    nframes = 0
 25    if start > 1:
 26        print(f"skipping {start-1} frames")
 27    if not has_comment_line:
 28        comment_line = ""
 29    while True:
 30        line = pf.readline()
 31
 32        if not line:
 33            if stream:
 34                sleep(interval)
 35                continue
 36            elif inside_frame or nat_read:
 37                raise Exception("Error: premature end of file!")
 38            else:
 39                break
 40
 41        line = line.strip()
 42
 43        if not inside_frame:
 44            if not nat_read:
 45                if line.startswith("#") or line == "":
 46                    continue
 47                nat = int(line.split()[0])
 48                nat_read = True
 49                iat = 0
 50                inside_frame = not has_comment_line
 51                xyz = np.zeros((nat, 3))
 52                symbols = []
 53                continue
 54
 55            # box = np.array(line.split(), dtype="float")
 56            comment_line = line
 57            inside_frame = True
 58            continue
 59
 60        if line.startswith("#") or line == "":
 61            raise Exception("Error: premature end of frame!")
 62
 63        if not nat_read:
 64            raise Exception("Error: nat not read!")
 65        ls = line.split()
 66        iat, s = (int(ls[0]), 1) if indexed else (iat + 1, 0)
 67        symbols.append(ls[s])
 68        xyz[iat - 1, :] = np.array([ls[s + 1], ls[s + 2], ls[s + 3]], dtype="float")
 69        if iat == nat:
 70            iframe += 1
 71            inside_frame = False
 72            nat_read = False
 73            if iframe < start:
 74                continue
 75            stride += 1
 76            if stride >= step:
 77                nframes += 1
 78                stride = 0
 79                yield symbols, xyz, comment_line
 80            if (max_frames is not None and nframes >= max_frames) or (
 81                stop > 0 and iframe >= stop
 82            ):
 83                break
 84
 85
 86def read_xyz(
 87    filename,
 88    has_comment_line=False,
 89    indexed=False,
 90    start=1,
 91    stop=-1,
 92    step=1,
 93    max_frames=None,
 94):
 95    return [
 96        frame
 97        for frame in xyz_reader(
 98            filename, has_comment_line, indexed, start, stop, step, max_frames
 99        )
100    ]
101
102
103def last_xyz_frame(filename, has_comment_line=False, indexed=False):
104    last_frame = None
105    for frame in xyz_reader(
106        filename, has_comment_line, indexed, start=-1, stop=-1, step=1, max_frames=1
107    ):
108        last_frame = frame
109    return last_frame
110
111
112def write_arc_frame(
113    f,
114    symbols,
115    coordinates,
116    types=None,
117    nbonds=None,
118    connectivity=None,
119    cell=None,
120    **kwargs,
121):
122    nat = len(symbols)
123    f.write(f"{nat}\n")
124    if cell is not None:
125        f.write(" ".join([f"{x: 15.5f}" for x in cell.flatten()]) + "\n")
126    # f.write(f'{axis} {axis} {axis} 90.0 90.0 90.0 \n')
127    for i in range(nat):
128        line = f"{i+1} {symbols[i]:3} {coordinates[i,0]: 15.3f} {coordinates[i,1]: 15.3f} {coordinates[i,2]: 15.3f}"
129        if types is not None:
130            line += f"   {types[i]}"
131        if connectivity is not None and nbonds is not None:
132            line += "  " + " ".join([str(x + 1) for x in connectivity[i, : nbonds[i]]])
133        f.write(line + "\n")
134    f.flush()
135
136
137def write_extxyz_frame(
138    f, symbols, coordinates, cell=None, properties={}, forces=None, **kwargs
139):
140    nat = len(symbols)
141    f.write(f"{nat}\n")
142    comment_line = ""
143    if cell is not None:
144        comment_line += (
145            'Lattice="' + " ".join([f"{x:.3f}" for x in cell.flatten()]) + '" '
146        )
147    comment_line += "Properties=species:S:1:pos:R:3"
148    if forces is not None:
149        comment_line += ":forces:R:3"
150    comment_line += " "
151    for k, v in properties.items():
152        comment_line += f"{k}={v} "
153    f.write(f"{comment_line}\n")
154    for i in range(nat):
155        line = f"{symbols[i]:3} {coordinates[i,0]: 15.5e} {coordinates[i,1]: 15.5e} {coordinates[i,2]: 15.5e}"
156        if forces is not None:
157            line += f" {forces[i,0]: 15.5e} {forces[i,1]: 15.5e} {forces[i,2]: 15.5e}"
158        f.write(f"{line}\n")
159    f.flush()
160
161
162def write_xyz_frame(f, symbols, coordinates,cell=None, **kwargs):
163    nat = len(symbols)
164    f.write(f"{nat}\n")
165    if cell is not None:
166        f.write(" ".join([f"{x:.3f}" for x in cell.flatten()]))
167    f.write("\n")
168    for i in range(nat):
169        f.write(
170            f"{symbols[i]:3} {coordinates[i,0]: 15.5e} {coordinates[i,1]: 15.5e} {coordinates[i,2]: 15.5e}\n"
171        )
172    f.flush()
173
174
175def human_time_duration(seconds: float):
176    """Convert seconds (duration) to human readable string
177
178    from https://gist.github.com/borgstrom/936ca741e885a1438c374824efb038b3
179    """
180
181    if seconds < 1.0:
182        return f"{seconds*1000:.3g} ms"
183    if seconds < 10.0:
184        return f"{seconds:.3g} s"
185
186    TIME_DURATION_UNITS = (
187        ("week", "s", 60 * 60 * 24 * 7),
188        ("day", "s", 60 * 60 * 24),
189        ("h", "", 60 * 60),
190        ("min", "", 60),
191        ("s", "", 1),
192    )
193    parts = []
194    for unit, plur, div in TIME_DURATION_UNITS:
195        amount, seconds = divmod(int(seconds), div)
196        if amount > 0:
197            parts.append(f"{amount} {unit}{plur if amount > 1 else ''}")
198    return " ".join(parts)
def xyz_reader( filename, has_comment_line=False, indexed=False, start=1, stop=-1, step=1, max_frames=None, stream=False, interval=2.0, sleep=<built-in function sleep>):
 6def xyz_reader(
 7    filename,
 8    has_comment_line=False,
 9    indexed=False,
10    start=1,
11    stop=-1,
12    step=1,
13    max_frames=None,
14    stream=False,
15    interval=2.0,
16    sleep=time.sleep,
17):
18    if stop > 0 and start > stop:
19        return
20    pf = open(filename, "r")
21    inside_frame = False
22    nat_read = False
23    iframe = 0
24    stride = step
25    nframes = 0
26    if start > 1:
27        print(f"skipping {start-1} frames")
28    if not has_comment_line:
29        comment_line = ""
30    while True:
31        line = pf.readline()
32
33        if not line:
34            if stream:
35                sleep(interval)
36                continue
37            elif inside_frame or nat_read:
38                raise Exception("Error: premature end of file!")
39            else:
40                break
41
42        line = line.strip()
43
44        if not inside_frame:
45            if not nat_read:
46                if line.startswith("#") or line == "":
47                    continue
48                nat = int(line.split()[0])
49                nat_read = True
50                iat = 0
51                inside_frame = not has_comment_line
52                xyz = np.zeros((nat, 3))
53                symbols = []
54                continue
55
56            # box = np.array(line.split(), dtype="float")
57            comment_line = line
58            inside_frame = True
59            continue
60
61        if line.startswith("#") or line == "":
62            raise Exception("Error: premature end of frame!")
63
64        if not nat_read:
65            raise Exception("Error: nat not read!")
66        ls = line.split()
67        iat, s = (int(ls[0]), 1) if indexed else (iat + 1, 0)
68        symbols.append(ls[s])
69        xyz[iat - 1, :] = np.array([ls[s + 1], ls[s + 2], ls[s + 3]], dtype="float")
70        if iat == nat:
71            iframe += 1
72            inside_frame = False
73            nat_read = False
74            if iframe < start:
75                continue
76            stride += 1
77            if stride >= step:
78                nframes += 1
79                stride = 0
80                yield symbols, xyz, comment_line
81            if (max_frames is not None and nframes >= max_frames) or (
82                stop > 0 and iframe >= stop
83            ):
84                break
def read_xyz( filename, has_comment_line=False, indexed=False, start=1, stop=-1, step=1, max_frames=None):
 87def read_xyz(
 88    filename,
 89    has_comment_line=False,
 90    indexed=False,
 91    start=1,
 92    stop=-1,
 93    step=1,
 94    max_frames=None,
 95):
 96    return [
 97        frame
 98        for frame in xyz_reader(
 99            filename, has_comment_line, indexed, start, stop, step, max_frames
100        )
101    ]
def last_xyz_frame(filename, has_comment_line=False, indexed=False):
104def last_xyz_frame(filename, has_comment_line=False, indexed=False):
105    last_frame = None
106    for frame in xyz_reader(
107        filename, has_comment_line, indexed, start=-1, stop=-1, step=1, max_frames=1
108    ):
109        last_frame = frame
110    return last_frame
def write_arc_frame( f, symbols, coordinates, types=None, nbonds=None, connectivity=None, cell=None, **kwargs):
113def write_arc_frame(
114    f,
115    symbols,
116    coordinates,
117    types=None,
118    nbonds=None,
119    connectivity=None,
120    cell=None,
121    **kwargs,
122):
123    nat = len(symbols)
124    f.write(f"{nat}\n")
125    if cell is not None:
126        f.write(" ".join([f"{x: 15.5f}" for x in cell.flatten()]) + "\n")
127    # f.write(f'{axis} {axis} {axis} 90.0 90.0 90.0 \n')
128    for i in range(nat):
129        line = f"{i+1} {symbols[i]:3} {coordinates[i,0]: 15.3f} {coordinates[i,1]: 15.3f} {coordinates[i,2]: 15.3f}"
130        if types is not None:
131            line += f"   {types[i]}"
132        if connectivity is not None and nbonds is not None:
133            line += "  " + " ".join([str(x + 1) for x in connectivity[i, : nbonds[i]]])
134        f.write(line + "\n")
135    f.flush()
def write_extxyz_frame( f, symbols, coordinates, cell=None, properties={}, forces=None, **kwargs):
138def write_extxyz_frame(
139    f, symbols, coordinates, cell=None, properties={}, forces=None, **kwargs
140):
141    nat = len(symbols)
142    f.write(f"{nat}\n")
143    comment_line = ""
144    if cell is not None:
145        comment_line += (
146            'Lattice="' + " ".join([f"{x:.3f}" for x in cell.flatten()]) + '" '
147        )
148    comment_line += "Properties=species:S:1:pos:R:3"
149    if forces is not None:
150        comment_line += ":forces:R:3"
151    comment_line += " "
152    for k, v in properties.items():
153        comment_line += f"{k}={v} "
154    f.write(f"{comment_line}\n")
155    for i in range(nat):
156        line = f"{symbols[i]:3} {coordinates[i,0]: 15.5e} {coordinates[i,1]: 15.5e} {coordinates[i,2]: 15.5e}"
157        if forces is not None:
158            line += f" {forces[i,0]: 15.5e} {forces[i,1]: 15.5e} {forces[i,2]: 15.5e}"
159        f.write(f"{line}\n")
160    f.flush()
def write_xyz_frame(f, symbols, coordinates, cell=None, **kwargs):
163def write_xyz_frame(f, symbols, coordinates,cell=None, **kwargs):
164    nat = len(symbols)
165    f.write(f"{nat}\n")
166    if cell is not None:
167        f.write(" ".join([f"{x:.3f}" for x in cell.flatten()]))
168    f.write("\n")
169    for i in range(nat):
170        f.write(
171            f"{symbols[i]:3} {coordinates[i,0]: 15.5e} {coordinates[i,1]: 15.5e} {coordinates[i,2]: 15.5e}\n"
172        )
173    f.flush()
def human_time_duration(seconds: float):
176def human_time_duration(seconds: float):
177    """Convert seconds (duration) to human readable string
178
179    from https://gist.github.com/borgstrom/936ca741e885a1438c374824efb038b3
180    """
181
182    if seconds < 1.0:
183        return f"{seconds*1000:.3g} ms"
184    if seconds < 10.0:
185        return f"{seconds:.3g} s"
186
187    TIME_DURATION_UNITS = (
188        ("week", "s", 60 * 60 * 24 * 7),
189        ("day", "s", 60 * 60 * 24),
190        ("h", "", 60 * 60),
191        ("min", "", 60),
192        ("s", "", 1),
193    )
194    parts = []
195    for unit, plur, div in TIME_DURATION_UNITS:
196        amount, seconds = divmod(int(seconds), div)
197        if amount > 0:
198            parts.append(f"{amount} {unit}{plur if amount > 1 else ''}")
199    return " ".join(parts)

Convert seconds (duration) to human readable string

from https://gist.github.com/borgstrom/936ca741e885a1438c374824efb038b3