# natoms, frames, comment, expected_cell, precision tests_read_xyz = [ (1, 1, 'just a string plus few numbers: 1.10 2 .1', default_cell_mat, 5), (2, 1, 'another random comment', default_cell_mat, 5), (1, 2, 'random comment', default_cell_mat, 5), (2, 2, 'random comment', default_cell_mat, 5), (10, 2, 'random comment', default_cell_mat, 5), (10, 10, 'random comment', default_cell_mat, 5), (2, 3, '# CELL(abcABC): 5.1 5.2 5.0 91.0 89 90', mt.abc2h(5.1, 5.2, 5.0, 91 * deg2rad, 89 * deg2rad, 90 * deg2rad), 5), (2, 3, '# CELL[GENH]: ' + cell_string, mt.abc2h(5.1, 5.2, 5.0, 91 * deg2rad, 89 * deg2rad, 90 * deg2rad), 5), (2, 3, '# CELL{H}: ' + cell_string, mt.abc2h(*mt.genh2abc(mt.abc2h(5.1, 5.2, 5.0, 91 * deg2rad, 89 * deg2rad, 90 * deg2rad))), 5), (2, 3, '100 aaa # CELL(abcABC): 5.1 5.2 5.0 91.0 89 90 100 aaa', mt.abc2h(5.1, 5.2, 5.0, 91 * deg2rad, 89 * deg2rad, 90 * deg2rad), 5), (2, 3, '100 aaa # CELL[GENH]: ' + cell_string + ' 100 aaa', mt.abc2h(5.1, 5.2, 5.0, 91 * deg2rad, 89 * deg2rad, 90 * deg2rad), 5), (2, 3, '# CELL{H}: ' + cell_string + ' 100 aaa', mt.abc2h(*mt.genh2abc(mt.abc2h(5.1, 5.2, 5.0, 91 * deg2rad, 89 * deg2rad, 90 * deg2rad))), 5), ] @pytest.fixture(params=tests_read_xyz) def create_random_xyz_traj_to_read(request): natoms, frames, comment, expected_cell, precision = request.param filedesc, xyz, atom_names = xyz_gen.xyz_traj_filedesc(natoms,
def read_xyz(filedesc): """Reads an XYZ-style file with i-PI style comments and returns data in raw format for further units transformation and other post processing. Args: filedesc: An open readable file object from a xyz formatted file with i-PI header comments. Returns: i-Pi comment line, cell array, data (positions, forces, etc.), atoms names and masses """ try: natoms = int(filedesc.next()) except (StopIteration, ValueError): raise EOFError comment = filedesc.next() # Extracting cell cell = [key.search(comment) for key in cell_re] usegenh = False if cell[0] is not None: # abcABC a, b, c = [float(x) for x in cell[0].group(1).split()[:3]] alpha, beta, gamma = [float(x) * deg2rad for x in cell[0].group(1).split()[3:6]] h = mt.abc2h(a, b, c, alpha, beta, gamma) elif cell[1] is not None: # H h = np.array(cell[1].group(1).split()[:9], float) h.resize((3, 3)) elif cell[2] is not None: # GENH genh = np.array(cell[2].group(1).split()[:9], float) genh.resize((3, 3)) invgenh = np.linalg.inv(genh) # convert back & forth from abcABC representation to get an upper triangular h h = mt.abc2h(*mt.genh2abc(genh)) usegenh = True else: # defaults to unit box h = np.array([[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, -1.0]]) cell = h qatoms = np.zeros(3 * natoms) names = np.zeros(natoms, dtype='|S4') masses = np.zeros(natoms) # Extracting a time-frame information atom_counter = 0 for iat, line in enumerate(filedesc): body = line.split() names[iat], masses[iat] = body[0], Elements.mass(body[0]) x, y, z = float(body[1]), float(body[2]), float(body[3]) if usegenh: # must convert from the input cell parameters to the internal convention u = np.array([x, y, z]) us = np.dot(u, invgenh) u = np.dot(h, us) x, y, z = u qatoms[3 * iat], qatoms[3 * iat + 1], qatoms[3 * iat + 2] = x, y, z atom_counter += 1 if atom_counter == natoms: break if natoms != len(names): raise ValueError("The number of atom records does not match the header of the xyz file.") return comment, cell, qatoms, names, masses
def read_xyz(filedesc): """Reads an XYZ-style file with i-PI style comments and returns data in raw format for further units transformation and other post processing. Args: filedesc: An open readable file object from a xyz formatted file with i-PI header comments. Returns: i-Pi comment line, cell array, data (positions, forces, etc.), atoms names and masses """ try: natoms = int(filedesc.next()) except (StopIteration, ValueError): raise EOFError comment = filedesc.next() # Extracting cell cell = [key.search(comment) for key in cell_re] usegenh = False if cell[0] is not None: # abcABC a, b, c = [float(x) for x in cell[0].group(1).split()[:3]] alpha, beta, gamma = [float(x) * deg2rad for x in cell[0].group(1).split()[3:6]] h = mt.abc2h(a, b, c, alpha, beta, gamma) elif cell[1] is not None: # GENH h = np.array(cell[1].group(1).split()[:9], float) h.resize((3, 3)) elif cell[2] is not None: # H genh = np.array(cell[2].group(1).split()[:9], float) genh.resize((3, 3)) invgenh = np.linalg.inv(genh) # convert back & forth from abcABC representation to get an upper triangular h h = mt.abc2h(*mt.genh2abc(genh)) usegenh = True else: # defaults to unit box h = np.array([[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, -1.0]]) cell = h qatoms = np.zeros(3 * natoms) names = np.zeros(natoms, dtype='|S4') masses = np.zeros(natoms) # Extracting a time-frame information atom_counter = 0 for iat, line in enumerate(filedesc): body = line.split() names[iat], masses[iat] = body[0], Elements.mass(body[0]) x, y, z = float(body[1]), float(body[2]), float(body[3]) # TODO: The following in matrices would use vectorial computaiton if usegenh: # must convert from the input cell parameters to the internal convention u = np.array([x, y, z]) us = np.dot(u, invgenh) u = np.dot(h, us) x, y, z = u qatoms[3 * iat], qatoms[3 * iat + 1], qatoms[3 * iat + 2] = x, y, z atom_counter += 1 if atom_counter == natoms: break if natoms != len(names): raise ValueError("The number of atom records does not match the header of the xyz file.") return comment, cell, qatoms, names, masses
5, ), ( 2, 3, "# CELL[GENH]: " + cell_string, mt.abc2h(5.1, 5.2, 5.0, 91 * deg2rad, 89 * deg2rad, 90 * deg2rad), 5, ), ( 2, 3, "# CELL{H}: " + cell_string, mt.abc2h( *mt.genh2abc( mt.abc2h(5.1, 5.2, 5.0, 91 * deg2rad, 89 * deg2rad, 90 * deg2rad) ) ), 5, ), ( 2, 3, "100 aaa # CELL(abcABC): 5.1 5.2 5.0 91.0 89 90 100 aaa", mt.abc2h(5.1, 5.2, 5.0, 91 * deg2rad, 89 * deg2rad, 90 * deg2rad), 5, ), ( 2, 3, "100 aaa # CELL[GENH]: " + cell_string + " 100 aaa",