ChessAnalysisPipeline 0.0.11__py3-none-any.whl → 0.0.13__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.
Potentially problematic release.
This version of ChessAnalysisPipeline might be problematic. Click here for more details.
- CHAP/__init__.py +2 -0
- CHAP/common/__init__.py +6 -2
- CHAP/common/models/map.py +217 -70
- CHAP/common/processor.py +249 -155
- CHAP/common/reader.py +175 -130
- CHAP/common/writer.py +150 -94
- CHAP/edd/models.py +458 -262
- CHAP/edd/processor.py +614 -354
- CHAP/edd/utils.py +746 -235
- CHAP/tomo/models.py +22 -18
- CHAP/tomo/processor.py +1215 -892
- CHAP/utils/fit.py +211 -127
- CHAP/utils/general.py +789 -610
- CHAP/utils/parfile.py +1 -9
- CHAP/utils/scanparsers.py +101 -52
- {ChessAnalysisPipeline-0.0.11.dist-info → ChessAnalysisPipeline-0.0.13.dist-info}/METADATA +1 -1
- {ChessAnalysisPipeline-0.0.11.dist-info → ChessAnalysisPipeline-0.0.13.dist-info}/RECORD +21 -21
- {ChessAnalysisPipeline-0.0.11.dist-info → ChessAnalysisPipeline-0.0.13.dist-info}/WHEEL +1 -1
- {ChessAnalysisPipeline-0.0.11.dist-info → ChessAnalysisPipeline-0.0.13.dist-info}/LICENSE +0 -0
- {ChessAnalysisPipeline-0.0.11.dist-info → ChessAnalysisPipeline-0.0.13.dist-info}/entry_points.txt +0 -0
- {ChessAnalysisPipeline-0.0.11.dist-info → ChessAnalysisPipeline-0.0.13.dist-info}/top_level.txt +0 -0
CHAP/common/reader.py
CHANGED
|
@@ -6,7 +6,7 @@ Description: Module for Writers used in multiple experiment-specific
|
|
|
6
6
|
workflows.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
#
|
|
9
|
+
# System modules
|
|
10
10
|
from os.path import (
|
|
11
11
|
isfile,
|
|
12
12
|
splitext,
|
|
@@ -14,138 +14,86 @@ from os.path import (
|
|
|
14
14
|
from sys import modules
|
|
15
15
|
from time import time
|
|
16
16
|
|
|
17
|
-
#
|
|
17
|
+
# Third party modules
|
|
18
|
+
import numpy as np
|
|
19
|
+
|
|
20
|
+
# Local modules
|
|
18
21
|
from CHAP import Reader
|
|
19
22
|
|
|
20
23
|
|
|
21
24
|
class BinaryFileReader(Reader):
|
|
22
|
-
"""Reader for binary files
|
|
25
|
+
"""Reader for binary files.
|
|
26
|
+
"""
|
|
23
27
|
def read(self, filename):
|
|
24
|
-
"""Return a content of a given file
|
|
28
|
+
"""Return a content of a given binary file.
|
|
25
29
|
|
|
26
|
-
:param filename: name of the
|
|
27
|
-
:
|
|
30
|
+
:param filename: The name of the binary file to read from.
|
|
31
|
+
:type filename: str
|
|
32
|
+
:return: The file content.
|
|
28
33
|
:rtype: binary
|
|
29
34
|
"""
|
|
30
|
-
|
|
31
35
|
with open(filename, 'rb') as file:
|
|
32
36
|
data = file.read()
|
|
33
37
|
return data
|
|
34
38
|
|
|
35
39
|
|
|
36
|
-
class
|
|
37
|
-
"""Reader for
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
the
|
|
40
|
+
class H5Reader(Reader):
|
|
41
|
+
"""Reader for h5 files.
|
|
42
|
+
"""
|
|
43
|
+
def read(self, filename, h5path='/'):
|
|
44
|
+
"""Return the data object stored at `h5path` in an h5-file.
|
|
41
45
|
|
|
42
|
-
:param filename: name of file
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
:
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
:type spec_config: dict, optional
|
|
50
|
-
:param detector_names: Detector prefixes to include raw data
|
|
51
|
-
for in the returned NXentry
|
|
52
|
-
:type detector_names: list[str]
|
|
53
|
-
:return: Data from the SPEC configuration provided
|
|
54
|
-
:rtype: nexusformat.nexus.NXentry
|
|
46
|
+
:param filename: The name of the h5-file to read from.
|
|
47
|
+
:type filename: str
|
|
48
|
+
:param h5path: The path to a specific location in the h5 file
|
|
49
|
+
to read data from, defaults to `'/'`
|
|
50
|
+
:type h5path: str, optional
|
|
51
|
+
:return: The object indicated by `filename` and `h5path`.
|
|
52
|
+
:rtype: object
|
|
55
53
|
"""
|
|
56
|
-
|
|
57
|
-
from
|
|
58
|
-
NXdata,
|
|
59
|
-
NXentry,
|
|
60
|
-
NXfield)
|
|
61
|
-
import numpy as np
|
|
62
|
-
from CHAP.common.models.map import SpecConfig
|
|
63
|
-
|
|
64
|
-
if filename is not None:
|
|
65
|
-
if spec_config is not None:
|
|
66
|
-
raise RuntimeError('Specify either filename or spec_config '
|
|
67
|
-
'in common.SpecReader, not both')
|
|
68
|
-
# Read the map configuration from file
|
|
69
|
-
if not isfile(filename):
|
|
70
|
-
raise OSError(f'input file does not exist ({filename})')
|
|
71
|
-
extension = splitext(filename)[1]
|
|
72
|
-
if extension in ('.yml', '.yaml'):
|
|
73
|
-
reader = YAMLReader()
|
|
74
|
-
else:
|
|
75
|
-
raise RuntimeError('input file has a non-implemented '
|
|
76
|
-
f'extension ({filename})')
|
|
77
|
-
spec_config = reader.read(filename)
|
|
78
|
-
elif not isinstance(spec_config, dict):
|
|
79
|
-
raise RuntimeError('Invalid parameter spec_config in '
|
|
80
|
-
f'common.SpecReader ({spec_config})')
|
|
54
|
+
# Third party modules
|
|
55
|
+
from h5py import File
|
|
81
56
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
spec_config = SpecConfig(**spec_config)
|
|
85
|
-
|
|
86
|
-
# Set up NXentry and add misc. CHESS-specific metadata
|
|
87
|
-
# as well as all spec_motors, scan_columns, and smb_pars
|
|
88
|
-
nxentry = NXentry(name=spec_config.experiment_type)
|
|
89
|
-
nxentry.spec_config = dumps(spec_config.dict())
|
|
90
|
-
nxentry.attrs['station'] = spec_config.station
|
|
91
|
-
nxentry.spec_scans = NXcollection()
|
|
92
|
-
for scans in spec_config.spec_scans:
|
|
93
|
-
nxscans = NXcollection()
|
|
94
|
-
nxentry.spec_scans[f'{scans.scanparsers[0].scan_name}'] = nxscans
|
|
95
|
-
nxscans.attrs['spec_file'] = str(scans.spec_file)
|
|
96
|
-
nxscans.attrs['scan_numbers'] = scans.scan_numbers
|
|
97
|
-
for scan_number in scans.scan_numbers:
|
|
98
|
-
scanparser = scans.get_scanparser(scan_number)
|
|
99
|
-
nxscans[scan_number] = NXcollection()
|
|
100
|
-
if hasattr(scanparser, 'spec_positioner_values'):
|
|
101
|
-
nxscans[scan_number].spec_motors = dumps(
|
|
102
|
-
{k:float(v) for k,v
|
|
103
|
-
in scanparser.spec_positioner_values.items()})
|
|
104
|
-
if hasattr(scanparser, 'spec_scan_data'):
|
|
105
|
-
nxscans[scan_number].scan_columns = dumps(
|
|
106
|
-
{k:list(v) for k,v
|
|
107
|
-
in scanparser.spec_scan_data.items() if len(v)})
|
|
108
|
-
if hasattr(scanparser, 'pars'):
|
|
109
|
-
nxscans[scan_number].smb_pars = dumps(
|
|
110
|
-
{k:v for k,v in scanparser.pars.items()})
|
|
111
|
-
if detector_names:
|
|
112
|
-
nxdata = NXdata()
|
|
113
|
-
nxscans[scan_number].data = nxdata
|
|
114
|
-
for detector_name in detector_names:
|
|
115
|
-
nxdata[detector_name] = NXfield(
|
|
116
|
-
value=scanparser.get_detector_data(detector_name))
|
|
117
|
-
|
|
118
|
-
return nxentry
|
|
57
|
+
data = File(filename, 'r')[h5path]
|
|
58
|
+
return data
|
|
119
59
|
|
|
120
60
|
|
|
121
61
|
class MapReader(Reader):
|
|
122
|
-
"""Reader for CHESS sample maps
|
|
123
|
-
|
|
62
|
+
"""Reader for CHESS sample maps.
|
|
63
|
+
"""
|
|
64
|
+
def read(
|
|
65
|
+
self, filename=None, map_config=None, detector_names=[],
|
|
66
|
+
inputdir=None):
|
|
124
67
|
"""Take a map configuration dictionary and return a
|
|
125
|
-
representation of the map as
|
|
126
|
-
data group will contain the raw data
|
|
127
|
-
of the map.
|
|
68
|
+
representation of the map as a NeXus NXentry object. The
|
|
69
|
+
NXentry's default data group will contain the raw data
|
|
70
|
+
collected over the course of the map.
|
|
128
71
|
|
|
129
|
-
:param filename: name of file with the map configuration
|
|
130
|
-
read and pass onto the constructor of
|
|
131
|
-
`CHAP.common.models.map.MapConfig`
|
|
72
|
+
:param filename: The name of a file with the map configuration
|
|
73
|
+
to read and pass onto the constructor of
|
|
74
|
+
`CHAP.common.models.map.MapConfig`, defaults to `None`.
|
|
132
75
|
:type filename: str, optional
|
|
133
|
-
:param map_config: map configuration to be passed directly to
|
|
134
|
-
the constructor of `CHAP.common.models.map.MapConfig
|
|
76
|
+
:param map_config: A map configuration to be passed directly to
|
|
77
|
+
the constructor of `CHAP.common.models.map.MapConfig`,
|
|
78
|
+
defaults to `None`.
|
|
135
79
|
:type map_config: dict, optional
|
|
136
80
|
:param detector_names: Detector prefixes to include raw data
|
|
137
|
-
for in the returned NXentry
|
|
138
|
-
:type detector_names: list[str]
|
|
139
|
-
:return: Data from the map configuration
|
|
81
|
+
for in the returned NeXus NXentry object, defaults to `[]`.
|
|
82
|
+
:type detector_names: list[str], optional
|
|
83
|
+
:return: Data from the provided map configuration.
|
|
140
84
|
:rtype: nexusformat.nexus.NXentry
|
|
141
85
|
"""
|
|
86
|
+
# Third party modules
|
|
142
87
|
from json import dumps
|
|
143
|
-
from nexusformat.nexus import (
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
88
|
+
from nexusformat.nexus import (
|
|
89
|
+
NXcollection,
|
|
90
|
+
NXdata,
|
|
91
|
+
NXentry,
|
|
92
|
+
NXfield,
|
|
93
|
+
NXsample,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# Local modules
|
|
149
97
|
from CHAP.common.models.map import MapConfig
|
|
150
98
|
|
|
151
99
|
if filename is not None:
|
|
@@ -168,7 +116,7 @@ class MapReader(Reader):
|
|
|
168
116
|
|
|
169
117
|
# Validate the map configuration provided by constructing a
|
|
170
118
|
# MapConfig
|
|
171
|
-
map_config = MapConfig(**map_config)
|
|
119
|
+
map_config = MapConfig(**map_config, inputdir=inputdir)
|
|
172
120
|
|
|
173
121
|
# Set up NXentry and add misc. CHESS-specific metadata
|
|
174
122
|
nxentry = NXentry(name=map_config.title)
|
|
@@ -185,7 +133,8 @@ class MapReader(Reader):
|
|
|
185
133
|
|
|
186
134
|
# Set up default data group
|
|
187
135
|
nxentry.data = NXdata()
|
|
188
|
-
|
|
136
|
+
if map_config.map_type == 'structured':
|
|
137
|
+
nxentry.data.attrs['axes'] = map_config.dims
|
|
189
138
|
for i, dim in enumerate(map_config.independent_dimensions[::-1]):
|
|
190
139
|
nxentry.data[dim.label] = NXfield(
|
|
191
140
|
value=map_config.coords[dim.label],
|
|
@@ -193,7 +142,8 @@ class MapReader(Reader):
|
|
|
193
142
|
attrs={'long_name': f'{dim.label} ({dim.units})',
|
|
194
143
|
'data_type': dim.data_type,
|
|
195
144
|
'local_name': dim.name})
|
|
196
|
-
|
|
145
|
+
if map_config.map_type == 'structured':
|
|
146
|
+
nxentry.data.attrs[f'{dim.label}_indices'] = i
|
|
197
147
|
|
|
198
148
|
# Create empty NXfields for all scalar data present in the
|
|
199
149
|
# provided map configuration
|
|
@@ -241,43 +191,134 @@ class MapReader(Reader):
|
|
|
241
191
|
|
|
242
192
|
|
|
243
193
|
class NexusReader(Reader):
|
|
244
|
-
"""Reader for NeXus files
|
|
194
|
+
"""Reader for NeXus files.
|
|
195
|
+
"""
|
|
245
196
|
def read(self, filename, nxpath='/'):
|
|
246
|
-
"""Return the NeXus object stored at `nxpath` in
|
|
247
|
-
file `filename`.
|
|
197
|
+
"""Return the NeXus object stored at `nxpath` in a NeXus file.
|
|
248
198
|
|
|
249
|
-
:param filename: name of the NeXus file to read from
|
|
199
|
+
:param filename: The name of the NeXus file to read from.
|
|
250
200
|
:type filename: str
|
|
251
|
-
:param nxpath: path to a specific
|
|
252
|
-
to read from, defaults to `'/'`
|
|
201
|
+
:param nxpath: The path to a specific location in the NeXus
|
|
202
|
+
file tree to read from, defaults to `'/'`
|
|
253
203
|
:type nxpath: str, optional
|
|
254
|
-
:raises nexusformat.nexus.NeXusError:
|
|
255
|
-
NeXus file or `nxpath` is not in
|
|
256
|
-
:return:
|
|
204
|
+
:raises nexusformat.nexus.NeXusError: If `filename` is not a
|
|
205
|
+
NeXus file or `nxpath` is not in its tree.
|
|
206
|
+
:return: The NeXus object indicated by `filename` and `nxpath`.
|
|
257
207
|
:rtype: nexusformat.nexus.NXobject
|
|
258
208
|
"""
|
|
259
|
-
|
|
209
|
+
# Third party modules
|
|
260
210
|
from nexusformat.nexus import nxload
|
|
261
211
|
|
|
262
212
|
nxobject = nxload(filename)[nxpath]
|
|
263
213
|
return nxobject
|
|
264
214
|
|
|
265
215
|
|
|
216
|
+
class SpecReader(Reader):
|
|
217
|
+
"""Reader for CHESS SPEC scans"""
|
|
218
|
+
def read(self, filename=None, spec_config=None, detector_names=[],
|
|
219
|
+
inputdir=None):
|
|
220
|
+
"""Take a SPEC configuration filename or dictionary and return
|
|
221
|
+
the raw data as a Nexus NXentry object.
|
|
222
|
+
|
|
223
|
+
:param filename: The name of file with the SPEC configuration
|
|
224
|
+
to read from to pass onto the constructor of
|
|
225
|
+
`CHAP.common.models.map.SpecConfig`, defaults to `None`.
|
|
226
|
+
:type filename: str, optional
|
|
227
|
+
:param spec_config: A SPEC configuration to be passed directly
|
|
228
|
+
to the constructor of `CHAP.common.models.map.SpecConfig`,
|
|
229
|
+
defaults to `None`.
|
|
230
|
+
:type spec_config: dict, optional
|
|
231
|
+
:param detector_names: Detector prefixes to include raw data
|
|
232
|
+
for in the returned NeXus NXentry object, defaults to `[]`.
|
|
233
|
+
:type detector_names: list[str], optional
|
|
234
|
+
:return: The data from the provided SPEC configuration.
|
|
235
|
+
:rtype: nexusformat.nexus.NXentry
|
|
236
|
+
"""
|
|
237
|
+
# Third party modules
|
|
238
|
+
from json import dumps
|
|
239
|
+
from nexusformat.nexus import (
|
|
240
|
+
NXcollection,
|
|
241
|
+
NXdata,
|
|
242
|
+
NXentry,
|
|
243
|
+
NXfield,
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
# Local modules
|
|
247
|
+
from CHAP.common.models.map import SpecConfig
|
|
248
|
+
|
|
249
|
+
if filename is not None:
|
|
250
|
+
if spec_config is not None:
|
|
251
|
+
raise RuntimeError('Specify either filename or spec_config '
|
|
252
|
+
'in common.SpecReader, not both')
|
|
253
|
+
# Read the map configuration from file
|
|
254
|
+
if not isfile(filename):
|
|
255
|
+
raise OSError(f'input file does not exist ({filename})')
|
|
256
|
+
extension = splitext(filename)[1]
|
|
257
|
+
if extension in ('.yml', '.yaml'):
|
|
258
|
+
reader = YAMLReader()
|
|
259
|
+
else:
|
|
260
|
+
raise RuntimeError('input file has a non-implemented '
|
|
261
|
+
f'extension ({filename})')
|
|
262
|
+
spec_config = reader.read(filename)
|
|
263
|
+
elif not isinstance(spec_config, dict):
|
|
264
|
+
raise RuntimeError('Invalid parameter spec_config in '
|
|
265
|
+
f'common.SpecReader ({spec_config})')
|
|
266
|
+
|
|
267
|
+
# Validate the SPEC configuration provided by constructing a
|
|
268
|
+
# SpecConfig
|
|
269
|
+
spec_config = SpecConfig(**spec_config, inputdir=inputdir)
|
|
270
|
+
|
|
271
|
+
# Set up NXentry and add misc. CHESS-specific metadata
|
|
272
|
+
# as well as all spec_motors, scan_columns, and smb_pars
|
|
273
|
+
nxentry = NXentry(name=spec_config.experiment_type)
|
|
274
|
+
nxentry.spec_config = dumps(spec_config.dict())
|
|
275
|
+
nxentry.attrs['station'] = spec_config.station
|
|
276
|
+
nxentry.spec_scans = NXcollection()
|
|
277
|
+
for scans in spec_config.spec_scans:
|
|
278
|
+
nxscans = NXcollection()
|
|
279
|
+
nxentry.spec_scans[f'{scans.scanparsers[0].scan_name}'] = nxscans
|
|
280
|
+
nxscans.attrs['spec_file'] = str(scans.spec_file)
|
|
281
|
+
nxscans.attrs['scan_numbers'] = scans.scan_numbers
|
|
282
|
+
for scan_number in scans.scan_numbers:
|
|
283
|
+
scanparser = scans.get_scanparser(scan_number)
|
|
284
|
+
nxscans[scan_number] = NXcollection()
|
|
285
|
+
if hasattr(scanparser, 'spec_positioner_values'):
|
|
286
|
+
nxscans[scan_number].spec_motors = dumps(
|
|
287
|
+
{k:float(v) for k,v
|
|
288
|
+
in scanparser.spec_positioner_values.items()})
|
|
289
|
+
if hasattr(scanparser, 'spec_scan_data'):
|
|
290
|
+
nxscans[scan_number].scan_columns = dumps(
|
|
291
|
+
{k:list(v) for k,v
|
|
292
|
+
in scanparser.spec_scan_data.items() if len(v)})
|
|
293
|
+
if hasattr(scanparser, 'pars'):
|
|
294
|
+
nxscans[scan_number].smb_pars = dumps(
|
|
295
|
+
{k:v for k,v in scanparser.pars.items()})
|
|
296
|
+
if detector_names:
|
|
297
|
+
nxdata = NXdata()
|
|
298
|
+
nxscans[scan_number].data = nxdata
|
|
299
|
+
for detector_name in detector_names:
|
|
300
|
+
nxdata[detector_name] = NXfield(
|
|
301
|
+
value=scanparser.get_detector_data(detector_name))
|
|
302
|
+
|
|
303
|
+
return nxentry
|
|
304
|
+
|
|
305
|
+
|
|
266
306
|
class URLReader(Reader):
|
|
267
|
-
"""Reader for data available over HTTPS
|
|
307
|
+
"""Reader for data available over HTTPS.
|
|
308
|
+
"""
|
|
268
309
|
def read(self, url, headers={}, timeout=10):
|
|
269
310
|
"""Make an HTTPS request to the provided URL and return the
|
|
270
|
-
results.
|
|
311
|
+
results. Headers for the request are optional.
|
|
271
312
|
|
|
272
|
-
:param url:
|
|
313
|
+
:param url: The URL to read.
|
|
273
314
|
:type url: str
|
|
274
|
-
:param headers:
|
|
275
|
-
`{}`
|
|
315
|
+
:param headers: Headers to attach to the request,
|
|
316
|
+
defaults to `{}`
|
|
276
317
|
:type headers: dict, optional
|
|
277
|
-
:return:
|
|
318
|
+
:return: The content of the response.
|
|
278
319
|
:rtype: object
|
|
279
320
|
"""
|
|
280
|
-
|
|
321
|
+
# System modules
|
|
281
322
|
import requests
|
|
282
323
|
|
|
283
324
|
resp = requests.get(url, headers=headers, timeout=timeout)
|
|
@@ -289,15 +330,17 @@ class URLReader(Reader):
|
|
|
289
330
|
|
|
290
331
|
|
|
291
332
|
class YAMLReader(Reader):
|
|
292
|
-
"""Reader for YAML files
|
|
333
|
+
"""Reader for YAML files.
|
|
334
|
+
"""
|
|
293
335
|
def read(self, filename):
|
|
294
336
|
"""Return a dictionary from the contents of a yaml file.
|
|
295
337
|
|
|
296
|
-
:param filename: name of the YAML file to read from
|
|
297
|
-
:
|
|
338
|
+
:param filename: The name of the YAML file to read from.
|
|
339
|
+
:type filename: str
|
|
340
|
+
:return: The contents of the file.
|
|
298
341
|
:rtype: dict
|
|
299
342
|
"""
|
|
300
|
-
|
|
343
|
+
# Third party modules
|
|
301
344
|
import yaml
|
|
302
345
|
|
|
303
346
|
with open(filename) as file:
|
|
@@ -306,5 +349,7 @@ class YAMLReader(Reader):
|
|
|
306
349
|
|
|
307
350
|
|
|
308
351
|
if __name__ == '__main__':
|
|
352
|
+
# Local modules
|
|
309
353
|
from CHAP.reader import main
|
|
354
|
+
|
|
310
355
|
main()
|