forked from diffpy/diffpy.structure
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathp_auto.py
More file actions
242 lines (198 loc) · 6.56 KB
/
p_auto.py
File metadata and controls
242 lines (198 loc) · 6.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
#!/usr/bin/env python
##############################################################################
#
# diffpy.structure by DANSE Diffraction group
# Simon J. L. Billinge
# (c) 2007 trustees of the Michigan State University.
# All rights reserved.
#
# File coded by: Pavol Juhas
#
# See AUTHORS.txt for a list of people who contributed.
# See LICENSE_DANSE.txt for license information.
#
##############################################################################
"""Parser for automatic file format detection.
This Parser does not provide the the `toLines()` method.
"""
import os
from typing import Any
from diffpy.structure.parsers import StructureParser, parser_index
from diffpy.structure.structureerrors import StructureFormatError
from diffpy.utils._deprecator import build_deprecation_message, deprecated
base = "diffpy.structure.P_auto"
removal_version = "4.0.0"
parseLines_deprecation_msg = build_deprecation_message(
base,
"parseLines",
"parse_lines",
removal_version,
)
class P_auto(StructureParser):
"""Parser with automatic detection of structure format.
This parser attempts to automatically detect the format of a given
structure file and parse it accordingly. When successful, it sets
its `format` attribute to the detected structure format.
Parameters
----------
**kw : dict
Keyword arguments for the structure parser.
Attributes
----------
format : str
Detected structure format. Initially set to "auto" and updated
after successful detection of the structure format.
pkw : dict
Keyword arguments passed to the parser.
"""
def __init__(self, **kw):
StructureParser.__init__(self)
self.format = "auto"
self.pkw = kw
return
# parseLines helpers
def _get_ordered_formats(self):
"""Build a list of relevance ordered structure formats.
This only works when `self.filename` has a known extension.
"""
from diffpy.structure.parsers import inputFormats
ofmts = [fmt for fmt in inputFormats() if fmt != "auto"]
if not self.filename:
return ofmts
# filename is defined here
filebase = os.path.basename(self.filename)
from fnmatch import fnmatch
# loop over copy of ofmts
for fmt in list(ofmts):
pattern = parser_index[fmt]["file_pattern"]
if pattern in ("*.*", "*"):
continue
anymatch = [1 for p in pattern.split("|") if fnmatch(filebase, p)]
if anymatch:
ofmts.remove(fmt)
ofmts.insert(0, fmt)
return ofmts
@deprecated(parseLines_deprecation_msg)
def parseLines(self, lines):
"""This function has been deprecated and will be removed in
version 4.0.0.
Please use diffpy.structure.P_auto.parse_lines instead.
"""
return self.parse_lines(lines)
def parse_lines(self, lines):
"""Detect format and create `Structure` instance from a list of
lines.
Set format attribute to the detected file format.
Parameters
----------
lines : list
List of lines with structure data.
Returns
-------
Structure
`Structure` object.
Raises
------
StructureFormatError
"""
return self._wrap_parse_method("parse_lines", lines)
def parse(self, s):
"""Detect format and create `Structure` instance from a string.
Set format attribute to the detected file format.
Parameters
----------
s : str
String with structure data.
Returns
-------
Structure
`Structure` object.
Raises
------
StructureFormatError
"""
return self._wrap_parse_method("parse", s)
def parseFile(self, filename):
"""Detect format and create Structure instance from an existing
file.
Set format attribute to the detected file format.
Parameters
----------
filename : str
Path to structure file.
Returns
-------
Structure
`Structure` object.
Raises
------
StructureFormatError
If the structure format is unknown or invalid.
IOError
If the file cannot be read.
"""
self.filename = filename
return self._wrap_parse_method("parseFile", filename)
def _wrap_parse_method(self, method: object, *args: object, **kwargs: object) -> Any:
"""A helper evaluator method that try the specified parse method
with each registered structure parser and return the first
successful result.
Structure parsers that match structure file extension are
tried first.
Parameters
----------
method : str
Name of the parse method to call.
*args : tuple
Positional arguments for the parse method.
**kwargs : dict
Keyword arguments for the parse method.
Returns
-------
Structure
`Structure` object.
Raises
------
StructureFormatError
"""
from diffpy.structure.parsers import getParser
ofmts = self._get_ordered_formats()
stru = None
# try all parsers in sequence
parsers_emsgs = []
for fmt in ofmts:
p = getParser(fmt, **self.pkw)
try:
pmethod = getattr(p, method)
stru = pmethod(*args, **kwargs)
self.format = fmt
break
except StructureFormatError as err:
parsers_emsgs.append("%s: %s" % (fmt, err))
except NotImplementedError:
pass
if stru is None:
emsg = "\n".join(
[
"Unknown or invalid structure format.",
"Errors per each tested structure format:",
]
+ parsers_emsgs
)
raise StructureFormatError(emsg)
self.__dict__.update(p.__dict__)
return stru
# End of class P_auto
# Routines -------------------------------------------------------------------
def getParser(**kw):
"""Return a new instance of the automatic parser.
Parameters
----------
**kw : dict
Keyword arguments for the structure parser
Returns
-------
P_auto
Instance of `P_auto`.
"""
return P_auto(**kw)