sagar.io.xyz 源代码
# -*- coding: utf-8 -*-
import collections
import operator
import numpy
from sagar.molecule.structure import Molecule
from sagar.element.base import get_symbol
[文档]def read_vasp(filename='XYZ'):
"""
Import filename with .xyz suffix
parameter:
filename: string, the filename
return: Molecule object.
"""
# TODO: read velocities, now not supported. or not needed?
with open(filename, "r") as f:
# _read_string return Molecule object.
return _read_string(f.read())
def _read_string(data):
"""
_read_string make io easy to be tested.
parameter: string of xyz input
return: Molecule object
"""
lines = [l for l in data.split('\n') if l.rstrip()]
total_atoms = int(lines[0])
comment = lines[1]
positions = []
atoms = []
for i in range(2, 2 + total_atoms):
s = lines[i].split()
atoms.append(s[0])
vec = float(s[1]), float(s[2]), float(s[3])
positions.append(vec)
return Molecule(positions, atoms)
[文档]def write_vasp(mol, filename='XYZ', suffix='.xyz', long_format=True):
"""
write xyz type into file.
always write atoms sorted xyz file.
parameters:
mol: Molecule object, the Molecule that you wanna write into xyz.
filename: string, filename of output file, default='XYZ'
suffix: string, suffix of filename, default='.xyz'
long_format: bool, if True format %.16f will be write, else %.6f
ref: https://gitlab.com/ase/ase/blob/master/ase/io/vasp.py
if optional parameters (filename and suffix) are not set,
the filename will be 'XYZ.xyz'
"""
filname_suffix = ''.join([filename, suffix])
with open(filname_suffix, "w") as f:
f.write(_write_string(cell, long_format))
def _write_string(mol, long_format, print_vacc=False):
"""
_write_string make io easy to be tested.
return: string represtent XYZ file fomat
"""
# 对原子种类合并排序,用以产生体系名称和原子顺序数目和正确的坐标排序
# sorted is a list of tuple(atom, na)
atoms_dict = collections.Counter(mol.atoms)
if not print_vacc:
del atoms_dict[0]
sorted_symbols = sorted(atoms_dict.items(), key=operator.itemgetter(0))
list_symbols = ["{:}{:}".format(get_symbol(atom), na)
for atom, na in sorted_symbols]
total_atoms = 0
for n in atoms_dict.values():
total_atoms += n
total_atoms = str(total_atoms)
total_atoms += '\n'
comment = ' '.join(list_symbols)
comment += '\n'
# argsort atoms and resort coor
idx = numpy.argsort(mol.atoms)
coord = mol.positions[idx]
atoms = mol.atoms[idx]
positions_string = ""
if long_format:
pos_form = '19.16f'
else:
pos_form = '9.6f'
for i, vec in enumerate(coord):
if atoms[i] == 0:
continue
positions_string += ' ' + get_symbol(atoms[i])
for v in vec:
positions_string += '{:{form}}'.format(v, form=pos_form)
positions_string += '\n'
xyz_string = ''.join([total_atoms,
comment,
positions_string])
return xyz_string