diffpy.structure 3.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- diffpy/Structure.py +35 -0
- diffpy/__init__.py +23 -0
- diffpy/structure/__init__.py +93 -0
- diffpy/structure/_legacy_importer.py +88 -0
- diffpy/structure/apps/__init__.py +17 -0
- diffpy/structure/apps/anyeye.py +284 -0
- diffpy/structure/apps/transtru.py +126 -0
- diffpy/structure/atom.py +544 -0
- diffpy/structure/expansion/__init__.py +27 -0
- diffpy/structure/expansion/makeellipsoid.py +129 -0
- diffpy/structure/expansion/shapeutils.py +44 -0
- diffpy/structure/expansion/supercell_mod.py +91 -0
- diffpy/structure/lattice.py +663 -0
- diffpy/structure/mmlibspacegroups.py +8154 -0
- diffpy/structure/parsers/__init__.py +83 -0
- diffpy/structure/parsers/p_auto.py +217 -0
- diffpy/structure/parsers/p_cif.py +876 -0
- diffpy/structure/parsers/p_discus.py +312 -0
- diffpy/structure/parsers/p_pdb.py +405 -0
- diffpy/structure/parsers/p_pdffit.py +290 -0
- diffpy/structure/parsers/p_rawxyz.py +149 -0
- diffpy/structure/parsers/p_xcfg.py +457 -0
- diffpy/structure/parsers/p_xyz.py +161 -0
- diffpy/structure/parsers/parser_index_mod.py +108 -0
- diffpy/structure/parsers/structureparser.py +80 -0
- diffpy/structure/pdffitstructure.py +109 -0
- diffpy/structure/sgtbxspacegroups.py +5198 -0
- diffpy/structure/spacegroupmod.py +329 -0
- diffpy/structure/spacegroups.py +1441 -0
- diffpy/structure/structure.py +866 -0
- diffpy/structure/structureerrors.py +35 -0
- diffpy/structure/symmetryutilities.py +1100 -0
- diffpy/structure/utils.py +126 -0
- diffpy/structure/version.py +26 -0
- diffpy.structure-3.2.0.dist-info/AUTHORS.rst +13 -0
- diffpy.structure-3.2.0.dist-info/LICENSE.rst +141 -0
- diffpy.structure-3.2.0.dist-info/LICENSE_DANSE.rst +50 -0
- diffpy.structure-3.2.0.dist-info/LICENSE_pymmlib.rst +203 -0
- diffpy.structure-3.2.0.dist-info/METADATA +197 -0
- diffpy.structure-3.2.0.dist-info/RECORD +42 -0
- diffpy.structure-3.2.0.dist-info/WHEEL +5 -0
- diffpy.structure-3.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
##############################################################################
|
|
3
|
+
#
|
|
4
|
+
# diffpy.structure by DANSE Diffraction group
|
|
5
|
+
# Simon J. L. Billinge
|
|
6
|
+
# (c) 2007 trustees of the Michigan State University.
|
|
7
|
+
# All rights reserved.
|
|
8
|
+
#
|
|
9
|
+
# File coded by: Pavol Juhas
|
|
10
|
+
#
|
|
11
|
+
# See AUTHORS.txt for a list of people who contributed.
|
|
12
|
+
# See LICENSE_DANSE.txt for license information.
|
|
13
|
+
#
|
|
14
|
+
##############################################################################
|
|
15
|
+
|
|
16
|
+
"""Parser for DISCUS structure format
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import sys
|
|
20
|
+
from functools import reduce
|
|
21
|
+
|
|
22
|
+
from diffpy.structure import Lattice, PDFFitStructure
|
|
23
|
+
from diffpy.structure.parsers import StructureParser
|
|
24
|
+
from diffpy.structure.structureerrors import StructureFormatError
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class P_discus(StructureParser):
|
|
28
|
+
"""Parser for DISCUS structure format. The parser chokes
|
|
29
|
+
on molecule and generator records.
|
|
30
|
+
|
|
31
|
+
Attributes
|
|
32
|
+
----------
|
|
33
|
+
format : str
|
|
34
|
+
File format name, default "discus".
|
|
35
|
+
nl : int
|
|
36
|
+
Line number of the current line being parsed.
|
|
37
|
+
lines : list of str
|
|
38
|
+
List of lines from the input file.
|
|
39
|
+
line : str
|
|
40
|
+
Current line being parsed.
|
|
41
|
+
stru : PDFFitStructure
|
|
42
|
+
Structure being parsed.
|
|
43
|
+
ignored_lines : list of str
|
|
44
|
+
List of lines that were ignored during parsing.
|
|
45
|
+
cell_read : bool
|
|
46
|
+
``True`` if cell record processed.
|
|
47
|
+
ncell_read : bool
|
|
48
|
+
``True`` if ncell record processed.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
def __init__(self):
|
|
52
|
+
StructureParser.__init__(self)
|
|
53
|
+
self.format = "discus"
|
|
54
|
+
# helper variables
|
|
55
|
+
self.nl = None
|
|
56
|
+
self.lines = None
|
|
57
|
+
self.line = None
|
|
58
|
+
self.stru = None
|
|
59
|
+
self.ignored_lines = []
|
|
60
|
+
self.cell_read = False
|
|
61
|
+
self.ncell_read = False
|
|
62
|
+
return
|
|
63
|
+
|
|
64
|
+
def parseLines(self, lines):
|
|
65
|
+
"""Parse list of lines in DISCUS format.
|
|
66
|
+
|
|
67
|
+
Parameters
|
|
68
|
+
----------
|
|
69
|
+
lines : list of str
|
|
70
|
+
List of lines from the input file.
|
|
71
|
+
|
|
72
|
+
Returns
|
|
73
|
+
-------
|
|
74
|
+
PDFFitStructure
|
|
75
|
+
Parsed `PDFFitStructure` instance.
|
|
76
|
+
|
|
77
|
+
Raises
|
|
78
|
+
------
|
|
79
|
+
StructureFormatError
|
|
80
|
+
If the file is not in DISCUS format.
|
|
81
|
+
"""
|
|
82
|
+
self.lines = lines
|
|
83
|
+
ilines = self._linesIterator()
|
|
84
|
+
self.stru = PDFFitStructure()
|
|
85
|
+
record_parsers = {
|
|
86
|
+
"cell": self._parse_cell,
|
|
87
|
+
"format": self._parse_format,
|
|
88
|
+
"generator": self._parse_not_implemented,
|
|
89
|
+
"molecule": self._parse_not_implemented,
|
|
90
|
+
"ncell": self._parse_ncell,
|
|
91
|
+
"spcgr": self._parse_spcgr,
|
|
92
|
+
"symmetry": self._parse_not_implemented,
|
|
93
|
+
"title": self._parse_title,
|
|
94
|
+
"shape": self._parse_shape,
|
|
95
|
+
}
|
|
96
|
+
try:
|
|
97
|
+
# parse header
|
|
98
|
+
for self.line in ilines:
|
|
99
|
+
words = self.line.split()
|
|
100
|
+
if not words or words[0][0] == "#":
|
|
101
|
+
continue
|
|
102
|
+
if words[0] == "atoms":
|
|
103
|
+
break
|
|
104
|
+
rp = record_parsers.get(words[0], self._parse_unknown_record)
|
|
105
|
+
rp(words)
|
|
106
|
+
# check if cell has been defined
|
|
107
|
+
if not self.cell_read:
|
|
108
|
+
emsg = "%d: unit cell not defined" % self.nl
|
|
109
|
+
raise StructureFormatError(emsg)
|
|
110
|
+
# parse atoms
|
|
111
|
+
for self.line in ilines:
|
|
112
|
+
words = self.line.replace(",", " ").split()
|
|
113
|
+
if not words or words[0][0] == "#":
|
|
114
|
+
continue
|
|
115
|
+
self._parse_atom(words)
|
|
116
|
+
# self consistency check
|
|
117
|
+
exp_natoms = reduce(lambda x, y: x * y, self.stru.pdffit["ncell"])
|
|
118
|
+
# only check if ncell record exists
|
|
119
|
+
if self.ncell_read and exp_natoms != len(self.stru):
|
|
120
|
+
emsg = "Expected %d atoms, read %d." % (exp_natoms, len(self.stru))
|
|
121
|
+
raise StructureFormatError(emsg)
|
|
122
|
+
# take care of superlattice
|
|
123
|
+
if self.stru.pdffit["ncell"][:3] != [1, 1, 1]:
|
|
124
|
+
latpars = list(self.stru.lattice.abcABG())
|
|
125
|
+
superlatpars = [latpars[i] * self.stru.pdffit["ncell"][i] for i in range(3)] + latpars[3:]
|
|
126
|
+
superlattice = Lattice(*superlatpars)
|
|
127
|
+
self.stru.placeInLattice(superlattice)
|
|
128
|
+
self.stru.pdffit["ncell"] = [1, 1, 1, exp_natoms]
|
|
129
|
+
except (ValueError, IndexError):
|
|
130
|
+
exc_type, exc_value, exc_traceback = sys.exc_info()
|
|
131
|
+
emsg = "%d: file is not in DISCUS format" % self.nl
|
|
132
|
+
e = StructureFormatError(emsg)
|
|
133
|
+
raise e.with_traceback(exc_traceback)
|
|
134
|
+
return self.stru
|
|
135
|
+
|
|
136
|
+
def toLines(self, stru):
|
|
137
|
+
"""Convert `Structure` stru to a list of lines in DISCUS format.
|
|
138
|
+
|
|
139
|
+
Parameters
|
|
140
|
+
----------
|
|
141
|
+
stru : Structure
|
|
142
|
+
Structure to be converted.
|
|
143
|
+
|
|
144
|
+
Returns
|
|
145
|
+
-------
|
|
146
|
+
list of str
|
|
147
|
+
List of lines in DISCUS format.
|
|
148
|
+
"""
|
|
149
|
+
self.stru = stru
|
|
150
|
+
# if necessary, convert self.stru to PDFFitStructure
|
|
151
|
+
if not isinstance(stru, PDFFitStructure):
|
|
152
|
+
self.stru = PDFFitStructure(stru)
|
|
153
|
+
# build the stru_pdffit dictionary initialized from the defaults
|
|
154
|
+
# in PDFFitStructure
|
|
155
|
+
stru_pdffit = PDFFitStructure().pdffit
|
|
156
|
+
if stru.pdffit:
|
|
157
|
+
stru_pdffit.update(stru.pdffit)
|
|
158
|
+
# here we can start
|
|
159
|
+
self.lines = lines = []
|
|
160
|
+
lines.append(("title " + self.stru.title).strip())
|
|
161
|
+
lines.append("spcgr " + stru_pdffit["spcgr"])
|
|
162
|
+
if stru_pdffit.get("spdiameter", 0.0) > 0.0:
|
|
163
|
+
line = "shape sphere, %g" % stru_pdffit["spdiameter"]
|
|
164
|
+
lines.append(line)
|
|
165
|
+
if stru_pdffit.get("stepcut", 0.0) > 0.0:
|
|
166
|
+
line = "shape stepcut, %g" % stru_pdffit["stepcut"]
|
|
167
|
+
lines.append(line)
|
|
168
|
+
lines.append("cell %9.6f, %9.6f, %9.6f, %9.6f, %9.6f, %9.6f" % self.stru.lattice.abcABG())
|
|
169
|
+
lines.append("ncell %9i, %9i, %9i, %9i" % (1, 1, 1, len(self.stru)))
|
|
170
|
+
lines.append("atoms")
|
|
171
|
+
for a in self.stru:
|
|
172
|
+
lines.append(
|
|
173
|
+
"%-4s %17.8f %17.8f %17.8f %12.4f" % (a.element.upper(), a.xyz[0], a.xyz[1], a.xyz[2], a.Bisoequiv)
|
|
174
|
+
)
|
|
175
|
+
return lines
|
|
176
|
+
|
|
177
|
+
def _linesIterator(self):
|
|
178
|
+
"""Iterator over `self.lines`, which increments `self.nl`"""
|
|
179
|
+
# ignore trailing empty lines
|
|
180
|
+
stop = len(self.lines)
|
|
181
|
+
while stop > 0 and self.lines[stop - 1].strip() == "":
|
|
182
|
+
stop -= 1
|
|
183
|
+
self.nl = 0
|
|
184
|
+
# read header of PDFFit file
|
|
185
|
+
for self.line in self.lines[:stop]:
|
|
186
|
+
self.nl += 1
|
|
187
|
+
yield self.line
|
|
188
|
+
pass
|
|
189
|
+
|
|
190
|
+
def _parse_cell(self, words):
|
|
191
|
+
"""Process the cell record from DISCUS structure file."""
|
|
192
|
+
# split again on spaces or commas
|
|
193
|
+
words = self.line.replace(",", " ").split()
|
|
194
|
+
latpars = [float(w) for w in words[1:7]]
|
|
195
|
+
try:
|
|
196
|
+
self.stru.lattice.setLatPar(*latpars)
|
|
197
|
+
except ZeroDivisionError:
|
|
198
|
+
emsg = "%d: Invalid lattice parameters - zero cell volume" % self.nl
|
|
199
|
+
raise StructureFormatError(emsg)
|
|
200
|
+
self.cell_read = True
|
|
201
|
+
return
|
|
202
|
+
|
|
203
|
+
def _parse_format(self, words):
|
|
204
|
+
"""Process the format record from DISCUS structure file."""
|
|
205
|
+
if words[1] == "pdffit":
|
|
206
|
+
emsg = "%d: file is not in DISCUS format" % self.nl
|
|
207
|
+
raise StructureFormatError(emsg)
|
|
208
|
+
return
|
|
209
|
+
|
|
210
|
+
def _parse_ncell(self, words):
|
|
211
|
+
"""Process the ncell record from DISCUS structure file."""
|
|
212
|
+
# split again on spaces or commas
|
|
213
|
+
words = self.line.replace(",", " ").split()
|
|
214
|
+
self.stru.pdffit["ncell"] = [int(w) for w in words[1:5]]
|
|
215
|
+
self.ncell_read = True
|
|
216
|
+
return
|
|
217
|
+
|
|
218
|
+
def _parse_spcgr(self, words):
|
|
219
|
+
"""Process the spcgr record from DISCUS structure file."""
|
|
220
|
+
self.stru.pdffit["spcgr"] = "".join(words[1:])
|
|
221
|
+
return
|
|
222
|
+
|
|
223
|
+
def _parse_title(self, words):
|
|
224
|
+
"""Process the title record from DISCUS structure file."""
|
|
225
|
+
self.stru.title = self.line.lstrip()[5:].strip()
|
|
226
|
+
return
|
|
227
|
+
|
|
228
|
+
def _parse_shape(self, words):
|
|
229
|
+
"""Process the shape record from DISCUS structure file.
|
|
230
|
+
|
|
231
|
+
Parameters
|
|
232
|
+
----------
|
|
233
|
+
words : list of str
|
|
234
|
+
List of words in the line.
|
|
235
|
+
|
|
236
|
+
Raises
|
|
237
|
+
------
|
|
238
|
+
StructureFormatError
|
|
239
|
+
Invalid type of particle shape correction.
|
|
240
|
+
"""
|
|
241
|
+
# strip away any commas
|
|
242
|
+
linefixed = " ".join(words).replace(",", " ")
|
|
243
|
+
wordsfixed = linefixed.split()
|
|
244
|
+
shapetype = wordsfixed[1]
|
|
245
|
+
if shapetype == "sphere":
|
|
246
|
+
self.stru.pdffit["spdiameter"] = float(words[2])
|
|
247
|
+
elif shapetype == "stepcut":
|
|
248
|
+
self.stru.pdffit["stepcut"] = float(words[2])
|
|
249
|
+
else:
|
|
250
|
+
emsg = "Invalid type of particle shape correction %r" % shapetype
|
|
251
|
+
raise StructureFormatError(emsg)
|
|
252
|
+
return
|
|
253
|
+
|
|
254
|
+
def _parse_atom(self, words):
|
|
255
|
+
"""Process atom records in DISCUS structure file."""
|
|
256
|
+
element = words[0][0:1].upper() + words[0][1:].lower()
|
|
257
|
+
xyz = [float(w) for w in words[1:4]]
|
|
258
|
+
Biso = float(words[4])
|
|
259
|
+
self.stru.addNewAtom(element, xyz)
|
|
260
|
+
a = self.stru.getLastAtom()
|
|
261
|
+
a.Bisoequiv = Biso
|
|
262
|
+
return
|
|
263
|
+
|
|
264
|
+
def _parse_unknown_record(self, words):
|
|
265
|
+
"""Process unknown record in DISCUS structure file.
|
|
266
|
+
|
|
267
|
+
Silently ignores the line and adds it to `self.ignored_lines`.
|
|
268
|
+
|
|
269
|
+
Parameters
|
|
270
|
+
----------
|
|
271
|
+
words : list of str
|
|
272
|
+
List of words in the line.
|
|
273
|
+
|
|
274
|
+
Raises
|
|
275
|
+
------
|
|
276
|
+
StructureFormatError
|
|
277
|
+
Unkown record.
|
|
278
|
+
"""
|
|
279
|
+
self.ignored_lines.append(self.line)
|
|
280
|
+
return
|
|
281
|
+
|
|
282
|
+
def _parse_not_implemented(self, words):
|
|
283
|
+
"""Process the unimplemented records from DISCUS structure file.
|
|
284
|
+
|
|
285
|
+
Parameters
|
|
286
|
+
----------
|
|
287
|
+
words : list of str
|
|
288
|
+
List of words in the line.
|
|
289
|
+
|
|
290
|
+
Raises
|
|
291
|
+
------
|
|
292
|
+
NotImplementedError
|
|
293
|
+
If the record is not implemented.
|
|
294
|
+
"""
|
|
295
|
+
emsg = "%d: reading of DISCUS record %r is not implemented." % (self.nl, words[0])
|
|
296
|
+
raise NotImplementedError(emsg)
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
# End of class P_pdffit
|
|
300
|
+
|
|
301
|
+
# Routines -------------------------------------------------------------------
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def getParser():
|
|
305
|
+
"""Return new `parser` object for DISCUS format.
|
|
306
|
+
|
|
307
|
+
Returns
|
|
308
|
+
-------
|
|
309
|
+
P_discus
|
|
310
|
+
Instance of `P_discus`.
|
|
311
|
+
"""
|
|
312
|
+
return P_discus()
|