-
Notifications
You must be signed in to change notification settings - Fork 838
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #423 from nisse3000/master
Added Xr class to I/O module
- Loading branch information
Showing
3 changed files
with
276 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
# coding: utf-8 | ||
# Copyright (c) Pymatgen Development Team. | ||
# Distributed under the terms of the MIT License. | ||
|
||
from __future__ import division, unicode_literals | ||
|
||
__author__ = "Nils Edvin Richard Zimmermann" | ||
__copyright__ = "Copyright 2016, The Materials Project" | ||
__version__ = "0.1" | ||
__maintainer__ = "Nils Edvin Richard Zimmermann" | ||
__email__ = "nils.e.r.zimmermann@gmail.com" | ||
__date__ = "June 23, 2016" | ||
|
||
import unittest2 as unittest | ||
import os | ||
|
||
from pymatgen.io.xr import Xr | ||
from pymatgen.io.vasp.inputs import Poscar | ||
from pymatgen.core.structure import Structure | ||
|
||
test_dir = os.path.join(os.path.dirname(__file__), "..", "..", "..", | ||
'test_files') | ||
|
||
class XrTest(unittest.TestCase): | ||
|
||
def setUp(self): | ||
|
||
filepath = os.path.join(test_dir, 'POSCAR') | ||
p = Poscar.from_file(filepath) | ||
self.xr = Xr(p.structure) | ||
|
||
def test_str(self): | ||
expected_string = """pymatgen 10.4118 6.0672 4.7595 | ||
90.000 90.000 90.000 | ||
24 0 | ||
0 Fe4 P4 O16 | ||
1 Fe 2.2773 4.5504 2.2601 | ||
2 Fe 2.9285 1.5168 4.6399 | ||
3 Fe 7.4832 4.5504 0.1196 | ||
4 Fe 8.1344 1.5168 2.4994 | ||
5 P 0.9851 1.5168 1.9906 | ||
6 P 4.2208 4.5504 4.3704 | ||
7 P 6.1910 1.5168 0.3891 | ||
8 P 9.4267 4.5504 2.7689 | ||
9 O 0.4516 4.5504 3.3656 | ||
10 O 1.0062 1.5168 3.5283 | ||
11 O 1.7253 0.2795 1.3583 | ||
12 O 1.7253 2.7541 1.3583 | ||
13 O 3.4806 3.3131 3.7380 | ||
14 O 3.4806 5.7876 3.7380 | ||
15 O 4.1997 4.5504 1.1486 | ||
16 O 4.7543 1.5168 0.9859 | ||
17 O 5.6575 4.5504 3.7736 | ||
18 O 6.2121 1.5168 3.6109 | ||
19 O 6.9312 0.2795 1.0215 | ||
20 O 6.9312 2.7541 1.0215 | ||
21 O 8.6864 3.3131 3.4012 | ||
22 O 8.6864 5.7876 3.4012 | ||
23 O 9.4055 4.5504 1.2312 | ||
24 O 9.9602 1.5168 1.3939 | ||
10.4118 0.0000 0.0000 | ||
0.0000 6.0672 0.0000 | ||
0.0000 0.0000 4.7595 | ||
10.4118 0.0000 0.0000 | ||
0.0000 6.0672 0.0000 | ||
0.0000 0.0000 4.7595""" | ||
self.assertEqual(str(self.xr), expected_string) | ||
|
||
def test_from_file(self): | ||
filename = os.path.join(test_dir, "EDI.xr") | ||
xr = Xr.from_file(filename) | ||
self.assertIsInstance(xr.structure, Structure) | ||
xr2 = Xr.from_file(filename, use_cores=False) | ||
self.assertIsInstance(xr2.structure, Structure) | ||
|
||
if __name__ == "__main__": | ||
unittest.main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
# coding: utf-8 | ||
# Copyright (c) Pymatgen Development Team. | ||
# Distributed under the terms of the MIT License. | ||
|
||
from __future__ import division, unicode_literals | ||
|
||
""" | ||
This module provides input and output mechanisms | ||
for the xr file format, which is a modified CSSR | ||
file format and, for example, used in GULP. | ||
In particular, the module makes it easy | ||
to remove shell positions from relaxations | ||
that employed core-shell models. | ||
""" | ||
|
||
|
||
__author__ = "Nils Edvin Richard Zimmermann" | ||
__copyright__ = "Copyright 2016, The Materials Project" | ||
__version__ = "0.1" | ||
__maintainer__ = "Nils Edvin Richard Zimmermann" | ||
__email__ = "nils.e.r.zimmermann@gmail.com" | ||
__date__ = "June 23, 2016" | ||
|
||
import re | ||
|
||
from six.moves import map | ||
import numpy as np | ||
|
||
from monty.io import zopen | ||
from math import fabs | ||
from pymatgen.core.lattice import Lattice | ||
from pymatgen.core.structure import Structure | ||
|
||
class Xr(object): | ||
""" | ||
Basic object for working with xr files. | ||
Args: | ||
structure (Structure/IStructure): Structure object to create the | ||
Xr object. | ||
""" | ||
|
||
def __init__(self, structure): | ||
if not structure.is_ordered: | ||
raise ValueError("Xr file can only be constructed from ordered " | ||
"structure") | ||
self.structure = structure | ||
|
||
def __str__(self): | ||
output = ["pymatgen {:.4f} {:.4f} {:.4f}" | ||
.format(*self.structure.lattice.abc), | ||
"{:.3f} {:.3f} {:.3f}" | ||
.format(*self.structure.lattice.angles), | ||
"{} 0".format(len(self.structure)), | ||
"0 {}".format(self.structure.formula)] | ||
# There are actually 10 more fields per site | ||
# in a typical xr file from GULP, for example. | ||
for i, site in enumerate(self.structure.sites): | ||
output.append("{} {} {:.4f} {:.4f} {:.4f}" | ||
.format(i + 1, site.specie, site.x, site.y, site.z)) | ||
mat = self.structure.lattice.matrix | ||
for i in range(2): | ||
for j in range(3): | ||
output.append("{:.4f} {:.4f} {:.4f}".format( | ||
mat[j][0], mat[j][1], mat[j][2])) | ||
return "\n".join(output) | ||
|
||
def write_file(self, filename): | ||
""" | ||
Write out an xr file. | ||
Args: | ||
filename (str): name of the file to write to. | ||
""" | ||
with zopen(filename, 'wt') as f: | ||
f.write(str(self) + "\n") | ||
|
||
@staticmethod | ||
def from_string(string, use_cores=True, thresh=1.e-4): | ||
""" | ||
Creates an Xr object from a string representation. | ||
Args: | ||
string (str): string representation of an Xr object. | ||
use_cores (bool): use core positions and discard shell | ||
positions if set to True (default). Otherwise, | ||
use shell positions and discard core positions. | ||
thresh (float): relative threshold for consistency check | ||
between cell parameters (lengths and angles) from | ||
header information and cell vectors, respectively. | ||
Returns: | ||
xr (Xr): Xr object corresponding to the input | ||
string representation. | ||
""" | ||
lines = string.split("\n") | ||
toks = lines[0].split() | ||
lengths = [float(toks[i]) for i in range(1, len(toks))] | ||
toks = lines[1].split() | ||
angles = [float(i) for i in toks[0:3]] | ||
toks = lines[2].split() | ||
nsites = int(toks[0]) | ||
mat = np.zeros((3,3), dtype=float) | ||
for i in range(3): | ||
toks = lines[4+nsites+i].split() | ||
toks2 = lines[4+nsites+i+3].split() | ||
for j, item in enumerate(toks): | ||
if item != toks2[j]: | ||
raise RuntimeError("expected both matrices" | ||
" to be the same in xr file") | ||
mat[i] = np.array([float(w) for w in toks]) | ||
lat = Lattice(mat) | ||
if fabs(lat.a-lengths[0])/fabs(lat.a) > thresh or \ | ||
fabs(lat.b-lengths[1])/fabs(lat.b) > thresh or \ | ||
fabs(lat.c-lengths[2])/fabs(lat.c) > thresh or \ | ||
fabs(lat.alpha-angles[0])/fabs(lat.alpha) > thresh or \ | ||
fabs(lat.beta-angles[1])/fabs(lat.beta) > thresh or \ | ||
fabs(lat.gamma-angles[2])/fabs(lat.gamma) > thresh: | ||
raise RuntimeError("cell parameters in header ("+str(lengths)+\ | ||
", "+str(angles)+") are not consistent with Cartesian"+\ | ||
" lattice vectors ("+str(lat.abc)+", "+\ | ||
str(lat.angles)+")") | ||
# Ignore line w/ index 3. | ||
sp = [] | ||
coords = [] | ||
for j in range(nsites): | ||
m = re.match("\d+\s+(\w+)\s+([0-9\-\.]+)\s+([0-9\-\.]+)\s+" + | ||
"([0-9\-\.]+)", lines[4+j].strip()) | ||
if m: | ||
tmp_sp = m.group(1) | ||
if use_cores and tmp_sp[len(tmp_sp)-2:] == "_s": | ||
continue | ||
if not use_cores and tmp_sp[len(tmp_sp)-2:] == "_c": | ||
continue | ||
if tmp_sp[len(tmp_sp)-2] == "_": | ||
sp.append(tmp_sp[0:len(tmp_sp)-2]) | ||
else: | ||
sp.append(tmp_sp) | ||
coords.append([float(m.group(i)) for i in range(2, 5)]) | ||
return Xr(Structure(lat, sp, coords, coords_are_cartesian=True)) | ||
|
||
@staticmethod | ||
def from_file(filename, use_cores=True, thresh=1.e-4): | ||
""" | ||
Reads an xr-formatted file to create an Xr object. | ||
Args: | ||
filename (str): name of file to read from. | ||
use_cores (bool): use core positions and discard shell | ||
positions if set to True (default). Otherwise, | ||
use shell positions and discard core positions. | ||
thresh (float): relative threshold for consistency check | ||
between cell parameters (lengths and angles) from | ||
header information and cell vectors, respectively. | ||
Returns: | ||
xr (Xr): Xr object corresponding to the input | ||
file. | ||
""" | ||
with zopen(filename, "rt") as f: | ||
return Xr.from_string( | ||
f.read(), use_cores=use_cores, | ||
thresh=thresh) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
somestring 6.8774 6.8774 6.3558 | ||
90.0 90.0 90.0 | ||
25 1 EDI structure | ||
1 bulk | ||
1 Si 1.84246 -0.00000 0.75253 0 0 0 0 0 0 0 0 4.000 0.00 | ||
2 Si 6.85980 1.86010 5.58528 0 0 0 0 0 0 0 0 4.000 0.00 | ||
3 Si 4.99970 -0.00000 0.75253 0 0 0 0 0 0 0 0 4.000 0.00 | ||
4 Si 6.85980 5.01733 5.58528 0 0 0 0 0 0 0 0 4.000 0.00 | ||
5 Si 6.85980 6.87743 3.16890 0 0 0 0 0 0 0 0 4.000 0.00 | ||
6 O_c 1.29725 1.31488 6.34680 0 0 0 0 0 0 0 0 0.869 74.92 | ||
7 O_s 1.21428 1.23192 6.34680 0 0 0 0 0 0 0 0 -2.869 74.92 | ||
8 O_c 5.54491 1.31488 6.34680 0 0 0 0 0 0 0 0 0.869 74.92 | ||
9 O_s 5.62788 1.23192 6.34680 0 0 0 0 0 0 0 0 -2.869 74.92 | ||
10 O_c 5.54491 5.56255 6.34680 0 0 0 0 0 0 0 0 0.869 74.92 | ||
11 O_s 5.62788 5.64551 6.34680 0 0 0 0 0 0 0 0 -2.869 74.92 | ||
12 O_c 1.29725 5.56255 6.34680 0 0 0 0 0 0 0 0 0.869 74.92 | ||
13 O_s 1.21428 5.64551 6.34680 0 0 0 0 0 0 0 0 -2.869 74.92 | ||
14 O_c 1.31620 6.87743 2.27055 0 0 0 0 0 0 0 0 0.869 74.92 | ||
15 O_s 1.22765 6.87743 2.20123 0 0 0 0 0 0 0 0 -2.869 74.92 | ||
16 O_c 6.85980 1.33384 4.06726 0 0 0 0 0 0 0 0 0.869 74.92 | ||
17 O_s 6.85980 1.24529 4.13658 0 0 0 0 0 0 0 0 -2.869 74.92 | ||
18 O_c 5.52596 6.87743 2.27055 0 0 0 0 0 0 0 0 0.869 74.92 | ||
19 O_s 5.61451 6.87743 2.20123 0 0 0 0 0 0 0 0 -2.869 74.92 | ||
20 O_c 6.85980 5.54359 4.06726 0 0 0 0 0 0 0 0 0.869 74.92 | ||
21 O_s 6.85980 5.63214 4.13658 0 0 0 0 0 0 0 0 -2.869 74.92 | ||
22 O_c 3.42108 -0.00000 0.75105 0 0 0 0 0 0 0 0 0.869 74.92 | ||
23 O_s 3.42108 -0.00000 0.75165 0 0 0 0 0 0 0 0 -2.869 74.92 | ||
24 O_c 6.85980 3.43871 5.58676 0 0 0 0 0 0 0 0 0.869 74.92 | ||
25 O_s 6.85980 3.43871 5.58616 0 0 0 0 0 0 0 0 -2.869 74.92 | ||
6.877431 0.000000 0.000000 | ||
0.000000 6.877431 -0.000000 | ||
0.000000 -0.000000 6.355796 | ||
6.877431 0.000000 0.000000 | ||
0.000000 6.877431 -0.000000 | ||
0.000000 -0.000000 6.355796 |