fennol.utils.io
1import time 2import numpy as np 3from . import cell_vectors_to_lengths_angles, parse_cell 4 5def xyz_reader( 6 filename, 7 has_comment_line=True, 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 at_count = 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 at_count += 1 68 try: 69 iat,s = (int(ls[0]),1) 70 indexed = True 71 except ValueError: 72 if indexed: 73 raise Exception("Error: line does not start with an integer index!") 74 iat, s = (iat+1, 0) 75 # iat, s = (int(ls[0]), 1) if indexed else (iat + 1, 0) 76 symbols.append(ls[s]) 77 xyz[iat - 1, :] = np.array([ls[s + 1], ls[s + 2], ls[s + 3]], dtype="float") 78 if at_count == nat: 79 iframe += 1 80 inside_frame = False 81 nat_read = False 82 if iframe < start: 83 continue 84 stride += 1 85 if stride >= step: 86 nframes += 1 87 stride = 0 88 yield symbols, xyz, comment_line 89 if (max_frames is not None and nframes >= max_frames) or ( 90 stop > 0 and iframe >= stop 91 ): 92 break 93 94 95def read_xyz( 96 filename, 97 has_comment_line=True, 98 indexed=False, 99 start=1, 100 stop=-1, 101 step=1, 102 max_frames=None, 103): 104 return [ 105 frame 106 for frame in xyz_reader( 107 filename, has_comment_line, indexed, start, stop, step, max_frames 108 ) 109 ] 110 111 112def last_xyz_frame(filename, has_comment_line=True, indexed=False): 113 last_frame = None 114 for frame in xyz_reader( 115 filename, has_comment_line, indexed, start=-1, stop=-1, step=1, max_frames=1 116 ): 117 last_frame = frame 118 return last_frame 119 120 121def write_arc_frame( 122 f, 123 symbols, 124 coordinates, 125 types=None, 126 nbonds=None, 127 connectivity=None, 128 cell=None, 129 **kwargs, 130): 131 nat = len(symbols) 132 f.write(f"{nat}\n") 133 if cell is not None: 134 box = cell_vectors_to_lengths_angles(parse_cell(cell)) 135 f.write(" ".join([f"{x: 15.5f}" for x in box]) + "\n") 136 # f.write(f'{axis} {axis} {axis} 90.0 90.0 90.0 \n') 137 for i in range(nat): 138 line = f"{i+1} {symbols[i]:3} {coordinates[i,0]: 15.3f} {coordinates[i,1]: 15.3f} {coordinates[i,2]: 15.3f}" 139 if types is not None: 140 line += f" {types[i]}" 141 if connectivity is not None and nbonds is not None: 142 line += " " + " ".join([str(x + 1) for x in connectivity[i, : nbonds[i]]]) 143 f.write(line + "\n") 144 f.flush() 145 146 147def write_extxyz_frame( 148 f, symbols, coordinates, cell=None, properties={}, forces=None, **kwargs 149): 150 nat = len(symbols) 151 f.write(f"{nat}\n") 152 comment_line = "" 153 if cell is not None: 154 cell = parse_cell(cell) 155 comment_line += ( 156 'Lattice="' + " ".join([f"{x:.3f}" for x in cell.flatten()]) + '" ' 157 ) 158 comment_line += "Properties=species:S:1:pos:R:3" 159 if forces is not None: 160 comment_line += ":forces:R:3" 161 comment_line += " " 162 for k, v in properties.items(): 163 comment_line += f"{k}={v} " 164 f.write(f"{comment_line}\n") 165 for i in range(nat): 166 line = f"{symbols[i]:3} {coordinates[i,0]: 15.5e} {coordinates[i,1]: 15.5e} {coordinates[i,2]: 15.5e}" 167 if forces is not None: 168 line += f" {forces[i,0]: 15.5e} {forces[i,1]: 15.5e} {forces[i,2]: 15.5e}" 169 f.write(f"{line}\n") 170 f.flush() 171 172 173def write_xyz_frame(f, symbols, coordinates,cell=None, **kwargs): 174 nat = len(symbols) 175 f.write(f"{nat}\n") 176 if cell is not None: 177 box = cell_vectors_to_lengths_angles(parse_cell(cell)) 178 f.write(" ".join([f"{x:.3f}" for x in box])) 179 f.write("\n") 180 for i in range(nat): 181 f.write( 182 f"{symbols[i]:3} {coordinates[i,0]: 15.5e} {coordinates[i,1]: 15.5e} {coordinates[i,2]: 15.5e}\n" 183 ) 184 f.flush() 185 186 187def human_time_duration(seconds: float): 188 """Convert seconds (duration) to human readable string 189 190 from https://gist.github.com/borgstrom/936ca741e885a1438c374824efb038b3 191 """ 192 193 if seconds < 1.0: 194 return f"{seconds*1000:.3g} ms" 195 if seconds < 10.0: 196 return f"{seconds:.3g} s" 197 198 TIME_DURATION_UNITS = ( 199 ("week", "s", 60 * 60 * 24 * 7), 200 ("day", "s", 60 * 60 * 24), 201 ("h", "", 60 * 60), 202 ("min", "", 60), 203 ("s", "", 1), 204 ) 205 parts = [] 206 for unit, plur, div in TIME_DURATION_UNITS: 207 amount, seconds = divmod(int(seconds), div) 208 if amount > 0: 209 parts.append(f"{amount} {unit}{plur if amount > 1 else ''}") 210 return " ".join(parts)
def
xyz_reader( filename, has_comment_line=True, 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=True, 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 at_count = 0 52 inside_frame = not has_comment_line 53 xyz = np.zeros((nat, 3)) 54 symbols = [] 55 continue 56 57 # box = np.array(line.split(), dtype="float") 58 comment_line = line 59 inside_frame = True 60 continue 61 62 if line.startswith("#") or line == "": 63 raise Exception("Error: premature end of frame!") 64 65 if not nat_read: 66 raise Exception("Error: nat not read!") 67 ls = line.split() 68 at_count += 1 69 try: 70 iat,s = (int(ls[0]),1) 71 indexed = True 72 except ValueError: 73 if indexed: 74 raise Exception("Error: line does not start with an integer index!") 75 iat, s = (iat+1, 0) 76 # iat, s = (int(ls[0]), 1) if indexed else (iat + 1, 0) 77 symbols.append(ls[s]) 78 xyz[iat - 1, :] = np.array([ls[s + 1], ls[s + 2], ls[s + 3]], dtype="float") 79 if at_count == nat: 80 iframe += 1 81 inside_frame = False 82 nat_read = False 83 if iframe < start: 84 continue 85 stride += 1 86 if stride >= step: 87 nframes += 1 88 stride = 0 89 yield symbols, xyz, comment_line 90 if (max_frames is not None and nframes >= max_frames) or ( 91 stop > 0 and iframe >= stop 92 ): 93 break
def
read_xyz( filename, has_comment_line=True, indexed=False, start=1, stop=-1, step=1, max_frames=None):
def
last_xyz_frame(filename, has_comment_line=True, indexed=False):
def
write_arc_frame( f, symbols, coordinates, types=None, nbonds=None, connectivity=None, cell=None, **kwargs):
122def write_arc_frame( 123 f, 124 symbols, 125 coordinates, 126 types=None, 127 nbonds=None, 128 connectivity=None, 129 cell=None, 130 **kwargs, 131): 132 nat = len(symbols) 133 f.write(f"{nat}\n") 134 if cell is not None: 135 box = cell_vectors_to_lengths_angles(parse_cell(cell)) 136 f.write(" ".join([f"{x: 15.5f}" for x in box]) + "\n") 137 # f.write(f'{axis} {axis} {axis} 90.0 90.0 90.0 \n') 138 for i in range(nat): 139 line = f"{i+1} {symbols[i]:3} {coordinates[i,0]: 15.3f} {coordinates[i,1]: 15.3f} {coordinates[i,2]: 15.3f}" 140 if types is not None: 141 line += f" {types[i]}" 142 if connectivity is not None and nbonds is not None: 143 line += " " + " ".join([str(x + 1) for x in connectivity[i, : nbonds[i]]]) 144 f.write(line + "\n") 145 f.flush()
def
write_extxyz_frame( f, symbols, coordinates, cell=None, properties={}, forces=None, **kwargs):
148def write_extxyz_frame( 149 f, symbols, coordinates, cell=None, properties={}, forces=None, **kwargs 150): 151 nat = len(symbols) 152 f.write(f"{nat}\n") 153 comment_line = "" 154 if cell is not None: 155 cell = parse_cell(cell) 156 comment_line += ( 157 'Lattice="' + " ".join([f"{x:.3f}" for x in cell.flatten()]) + '" ' 158 ) 159 comment_line += "Properties=species:S:1:pos:R:3" 160 if forces is not None: 161 comment_line += ":forces:R:3" 162 comment_line += " " 163 for k, v in properties.items(): 164 comment_line += f"{k}={v} " 165 f.write(f"{comment_line}\n") 166 for i in range(nat): 167 line = f"{symbols[i]:3} {coordinates[i,0]: 15.5e} {coordinates[i,1]: 15.5e} {coordinates[i,2]: 15.5e}" 168 if forces is not None: 169 line += f" {forces[i,0]: 15.5e} {forces[i,1]: 15.5e} {forces[i,2]: 15.5e}" 170 f.write(f"{line}\n") 171 f.flush()
def
write_xyz_frame(f, symbols, coordinates, cell=None, **kwargs):
174def write_xyz_frame(f, symbols, coordinates,cell=None, **kwargs): 175 nat = len(symbols) 176 f.write(f"{nat}\n") 177 if cell is not None: 178 box = cell_vectors_to_lengths_angles(parse_cell(cell)) 179 f.write(" ".join([f"{x:.3f}" for x in box])) 180 f.write("\n") 181 for i in range(nat): 182 f.write( 183 f"{symbols[i]:3} {coordinates[i,0]: 15.5e} {coordinates[i,1]: 15.5e} {coordinates[i,2]: 15.5e}\n" 184 ) 185 f.flush()
def
human_time_duration(seconds: float):
188def human_time_duration(seconds: float): 189 """Convert seconds (duration) to human readable string 190 191 from https://gist.github.com/borgstrom/936ca741e885a1438c374824efb038b3 192 """ 193 194 if seconds < 1.0: 195 return f"{seconds*1000:.3g} ms" 196 if seconds < 10.0: 197 return f"{seconds:.3g} s" 198 199 TIME_DURATION_UNITS = ( 200 ("week", "s", 60 * 60 * 24 * 7), 201 ("day", "s", 60 * 60 * 24), 202 ("h", "", 60 * 60), 203 ("min", "", 60), 204 ("s", "", 1), 205 ) 206 parts = [] 207 for unit, plur, div in TIME_DURATION_UNITS: 208 amount, seconds = divmod(int(seconds), div) 209 if amount > 0: 210 parts.append(f"{amount} {unit}{plur if amount > 1 else ''}") 211 return " ".join(parts)
Convert seconds (duration) to human readable string
from https://gist.github.com/borgstrom/936ca741e885a1438c374824efb038b3