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/processor.py
CHANGED
|
@@ -8,19 +8,84 @@ Description: Module for Processors used in multiple experiment-specific
|
|
|
8
8
|
workflows.
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
-
#
|
|
12
|
-
|
|
13
|
-
from time import time
|
|
11
|
+
# Third party modules
|
|
12
|
+
import numpy as np
|
|
14
13
|
|
|
15
|
-
#
|
|
14
|
+
# Local modules
|
|
16
15
|
from CHAP import Processor
|
|
17
16
|
|
|
18
17
|
|
|
18
|
+
class AnimationProcessor(Processor):
|
|
19
|
+
"""A Processor to show and return an animation.
|
|
20
|
+
"""
|
|
21
|
+
def process(
|
|
22
|
+
self, data, num_frames, axis=0, interval=1000, blit=True,
|
|
23
|
+
repeat=True, repeat_delay=1000):
|
|
24
|
+
"""Show and return an animation of image slices from a dataset
|
|
25
|
+
contained in `data`.
|
|
26
|
+
|
|
27
|
+
:param data: Input data.
|
|
28
|
+
:type data: CHAP.pipeline.PipelineData
|
|
29
|
+
:param num_frames: Number of frames for the animation.
|
|
30
|
+
:type num_frames: int
|
|
31
|
+
:param axis: Axis direction of the image slices,
|
|
32
|
+
defaults to `0`
|
|
33
|
+
:type axis: int, optional
|
|
34
|
+
:param interval: Delay between frames in milliseconds,
|
|
35
|
+
defaults to `1000`
|
|
36
|
+
:type interval: int, optional
|
|
37
|
+
:param blit: Whether blitting is used to optimize drawing,
|
|
38
|
+
default to `True`
|
|
39
|
+
:type blit: bool, optional
|
|
40
|
+
:param repeat: Whether the animation repeats when the sequence
|
|
41
|
+
of frames is completed, defaults to `True`
|
|
42
|
+
:type repeat: bool, optional
|
|
43
|
+
:param repeat_delay: Delay in milliseconds between consecutive
|
|
44
|
+
animation runs if repeat is `True`, defaults to `1000`
|
|
45
|
+
:type repeat_delay: int, optional
|
|
46
|
+
:return: The matplotlib animation.
|
|
47
|
+
:rtype: matplotlib.animation.ArtistAnimation
|
|
48
|
+
"""
|
|
49
|
+
# Third party modules
|
|
50
|
+
import matplotlib.animation as animation
|
|
51
|
+
import matplotlib.pyplot as plt
|
|
52
|
+
|
|
53
|
+
# Get the frames
|
|
54
|
+
data = self.unwrap_pipelinedata(data)[-1]
|
|
55
|
+
delta = int(data.shape[axis]/(num_frames+1))
|
|
56
|
+
indices = np.linspace(delta, data.shape[axis]-delta, num_frames)
|
|
57
|
+
if data.ndim == 3:
|
|
58
|
+
if not axis:
|
|
59
|
+
frames = [data[int(index)] for index in indices]
|
|
60
|
+
elif axis == 1:
|
|
61
|
+
frames = [data[:,int(index),:] for index in indices]
|
|
62
|
+
elif axis == 2:
|
|
63
|
+
frames = [data[:,:,int(index)] for index in indices]
|
|
64
|
+
else:
|
|
65
|
+
raise ValueError('Invalid data dimension (must be 2D or 3D)')
|
|
66
|
+
|
|
67
|
+
fig = plt.figure()
|
|
68
|
+
# vmin = np.min(frames)/8
|
|
69
|
+
# vmax = np.max(frames)/8
|
|
70
|
+
ims = [[plt.imshow(
|
|
71
|
+
#frames[n], vmin=vmin,vmax=vmax, cmap='gray',
|
|
72
|
+
frames[n], cmap='gray',
|
|
73
|
+
animated=True)]
|
|
74
|
+
for n in range(num_frames)]
|
|
75
|
+
ani = animation.ArtistAnimation(
|
|
76
|
+
fig, ims, interval=interval, blit=blit, repeat=repeat,
|
|
77
|
+
repeat_delay=repeat_delay)
|
|
78
|
+
|
|
79
|
+
plt.show()
|
|
80
|
+
|
|
81
|
+
return ani
|
|
82
|
+
|
|
83
|
+
|
|
19
84
|
class AsyncProcessor(Processor):
|
|
20
85
|
"""A Processor to process multiple sets of input data via asyncio
|
|
21
|
-
module
|
|
86
|
+
module.
|
|
22
87
|
|
|
23
|
-
:ivar mgr: The `Processor` used to process every set of input data
|
|
88
|
+
:ivar mgr: The `Processor` used to process every set of input data.
|
|
24
89
|
:type mgr: Processor
|
|
25
90
|
"""
|
|
26
91
|
def __init__(self, mgr):
|
|
@@ -31,31 +96,31 @@ class AsyncProcessor(Processor):
|
|
|
31
96
|
"""Asynchronously process the input documents with the
|
|
32
97
|
`self.mgr` `Processor`.
|
|
33
98
|
|
|
34
|
-
:param data:
|
|
99
|
+
:param data: Input data documents to process.
|
|
35
100
|
:type docs: iterable
|
|
36
101
|
"""
|
|
37
|
-
|
|
102
|
+
# System modules
|
|
38
103
|
import asyncio
|
|
39
104
|
|
|
40
105
|
async def task(mgr, doc):
|
|
41
|
-
"""Process given data using provided `Processor
|
|
106
|
+
"""Process given data using provided `Processor`.
|
|
42
107
|
|
|
43
|
-
:param mgr:
|
|
108
|
+
:param mgr: The object that will process given data.
|
|
44
109
|
:type mgr: Processor
|
|
45
|
-
:param doc:
|
|
110
|
+
:param doc: The data to process.
|
|
46
111
|
:type doc: object
|
|
47
|
-
:return: processed data
|
|
112
|
+
:return: The processed data.
|
|
48
113
|
:rtype: object
|
|
49
114
|
"""
|
|
50
115
|
return mgr.process(doc)
|
|
51
116
|
|
|
52
117
|
async def execute_tasks(mgr, docs):
|
|
53
118
|
"""Process given set of documents using provided task
|
|
54
|
-
manager
|
|
119
|
+
manager.
|
|
55
120
|
|
|
56
|
-
:param mgr:
|
|
121
|
+
:param mgr: The object that will process all documents.
|
|
57
122
|
:type mgr: Processor
|
|
58
|
-
:param docs:
|
|
123
|
+
:param docs: The set of data documents to process.
|
|
59
124
|
:type doc: iterable
|
|
60
125
|
"""
|
|
61
126
|
coroutines = [task(mgr, d) for d in docs]
|
|
@@ -64,22 +129,56 @@ class AsyncProcessor(Processor):
|
|
|
64
129
|
asyncio.run(execute_tasks(self.mgr, data))
|
|
65
130
|
|
|
66
131
|
|
|
67
|
-
class
|
|
68
|
-
"""A
|
|
132
|
+
class ImageProcessor(Processor):
|
|
133
|
+
"""A Processor to plot an image slice from a dataset.
|
|
134
|
+
"""
|
|
135
|
+
def process(self, data, index=0, axis=0):
|
|
136
|
+
"""Plot an image from a dataset contained in `data` and return
|
|
137
|
+
the full dataset.
|
|
138
|
+
|
|
139
|
+
:param data: Input data.
|
|
140
|
+
:type data: CHAP.pipeline.PipelineData
|
|
141
|
+
:param index: Array index of the slice of data to plot,
|
|
142
|
+
defaults to `0`
|
|
143
|
+
:type index: int, optional
|
|
144
|
+
:param axis: Axis direction of the image slice,
|
|
145
|
+
defaults to `0`
|
|
146
|
+
:type axis: int, optional
|
|
147
|
+
:return: The full input dataset.
|
|
148
|
+
:rtype: object
|
|
149
|
+
"""
|
|
150
|
+
# Local modules
|
|
151
|
+
from CHAP.utils.general import quick_imshow
|
|
152
|
+
|
|
153
|
+
data = self.unwrap_pipelinedata(data)[0]
|
|
154
|
+
if data.ndim == 2:
|
|
155
|
+
quick_imshow(data, block=True)
|
|
156
|
+
elif data.ndim == 3:
|
|
157
|
+
if not axis:
|
|
158
|
+
quick_imshow(data[index], block=True)
|
|
159
|
+
elif axis == 1:
|
|
160
|
+
quick_imshow(data[:,index,:], block=True)
|
|
161
|
+
elif axis == 2:
|
|
162
|
+
quick_imshow(data[:,:,index], block=True)
|
|
163
|
+
else:
|
|
164
|
+
raise ValueError(f'Invalid parameter axis ({axis})')
|
|
165
|
+
else:
|
|
166
|
+
raise ValueError('Invalid data dimension (must be 2D or 3D)')
|
|
167
|
+
|
|
168
|
+
return data
|
|
69
169
|
|
|
170
|
+
|
|
171
|
+
class IntegrationProcessor(Processor):
|
|
172
|
+
"""A processor for integrating 2D data with pyFAI.
|
|
173
|
+
"""
|
|
70
174
|
def process(self, data):
|
|
71
175
|
"""Integrate the input data with the integration method and
|
|
72
|
-
keyword arguments supplied and return the results.
|
|
176
|
+
keyword arguments supplied in `data` and return the results.
|
|
73
177
|
|
|
74
|
-
:param data:
|
|
178
|
+
:param data: Input data, containing the raw data, integration
|
|
75
179
|
method, and keyword args for the integration method.
|
|
76
|
-
:type data:
|
|
77
|
-
|
|
78
|
-
:param integration_method: the method of a
|
|
79
|
-
`pyFAI.azimuthalIntegrator.AzimuthalIntegrator` or
|
|
80
|
-
`pyFAI.multi_geometry.MultiGeometry` that returns the
|
|
81
|
-
desired integration results.
|
|
82
|
-
:return: integrated raw data
|
|
180
|
+
:type data: CHAP.pipeline.PipelineData
|
|
181
|
+
:return: Integrated raw data.
|
|
83
182
|
:rtype: pyFAI.containers.IntegrateResult
|
|
84
183
|
"""
|
|
85
184
|
detector_data, integration_method, integration_kwargs = data
|
|
@@ -88,26 +187,23 @@ class IntegrationProcessor(Processor):
|
|
|
88
187
|
|
|
89
188
|
|
|
90
189
|
class IntegrateMapProcessor(Processor):
|
|
91
|
-
"""
|
|
92
|
-
|
|
93
|
-
|
|
190
|
+
"""A processor that takes a map and integration configuration and
|
|
191
|
+
returns a NeXus NXprocesss object containing a map of the
|
|
192
|
+
integrated detector data requested.
|
|
94
193
|
"""
|
|
95
|
-
|
|
96
194
|
def process(self, data):
|
|
97
195
|
"""Process the output of a `Reader` that contains a map and
|
|
98
|
-
integration configuration and return a
|
|
99
|
-
|
|
100
|
-
integrated detector data requested
|
|
196
|
+
integration configuration and return a NeXus NXprocess object
|
|
197
|
+
containing a map of the integrated detector data requested.
|
|
101
198
|
|
|
102
|
-
:param data:
|
|
103
|
-
|
|
104
|
-
least one item
|
|
199
|
+
:param data: Input data, containing at least one item
|
|
200
|
+
with the value `'MapConfig'` for the `'schema'` key, and at
|
|
201
|
+
least one item with the value `'IntegrationConfig'` for the
|
|
105
202
|
`'schema'` key.
|
|
106
|
-
:type data:
|
|
107
|
-
:return:
|
|
203
|
+
:type data: CHAP.pipeline.PipelineData
|
|
204
|
+
:return: Integrated data and process metadata.
|
|
108
205
|
:rtype: nexusformat.nexus.NXprocess
|
|
109
206
|
"""
|
|
110
|
-
|
|
111
207
|
map_config = self.get_config(
|
|
112
208
|
data, 'common.models.map.MapConfig')
|
|
113
209
|
integration_config = self.get_config(
|
|
@@ -118,27 +214,31 @@ class IntegrateMapProcessor(Processor):
|
|
|
118
214
|
|
|
119
215
|
def get_nxprocess(self, map_config, integration_config):
|
|
120
216
|
"""Use a `MapConfig` and `IntegrationConfig` to construct a
|
|
121
|
-
|
|
217
|
+
NeXus NXprocess object.
|
|
122
218
|
|
|
123
|
-
:param map_config:
|
|
219
|
+
:param map_config: A valid map configuration.
|
|
124
220
|
:type map_config: MapConfig
|
|
125
|
-
:param integration_config:
|
|
126
|
-
:type integration_config: IntegrationConfig
|
|
127
|
-
:return:
|
|
128
|
-
in a NeXus structure
|
|
221
|
+
:param integration_config: A valid integration configuration
|
|
222
|
+
:type integration_config: IntegrationConfig.
|
|
223
|
+
:return: The integrated detector data and metadata.
|
|
129
224
|
:rtype: nexusformat.nexus.NXprocess
|
|
130
225
|
"""
|
|
226
|
+
# System modules
|
|
227
|
+
from json import dumps
|
|
228
|
+
from time import time
|
|
229
|
+
|
|
230
|
+
# Third party modules
|
|
231
|
+
from nexusformat.nexus import (
|
|
232
|
+
NXdata,
|
|
233
|
+
NXdetector,
|
|
234
|
+
NXfield,
|
|
235
|
+
NXprocess,
|
|
236
|
+
)
|
|
237
|
+
import pyFAI
|
|
131
238
|
|
|
132
239
|
self.logger.debug('Constructing NXprocess')
|
|
133
240
|
t0 = time()
|
|
134
241
|
|
|
135
|
-
from nexusformat.nexus import (NXdata,
|
|
136
|
-
NXdetector,
|
|
137
|
-
NXfield,
|
|
138
|
-
NXprocess)
|
|
139
|
-
import numpy as np
|
|
140
|
-
import pyFAI
|
|
141
|
-
|
|
142
242
|
nxprocess = NXprocess(name=integration_config.title)
|
|
143
243
|
|
|
144
244
|
nxprocess.map_config = dumps(map_config.dict())
|
|
@@ -255,24 +355,21 @@ class IntegrateMapProcessor(Processor):
|
|
|
255
355
|
|
|
256
356
|
|
|
257
357
|
class MapProcessor(Processor):
|
|
258
|
-
"""A Processor
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
configuration.
|
|
358
|
+
"""A Processor that takes a map configuration and returns a NeXus
|
|
359
|
+
NXentry object representing that map's metadata and any
|
|
360
|
+
scalar-valued raw data requested by the supplied map configuration.
|
|
262
361
|
"""
|
|
263
|
-
|
|
264
362
|
def process(self, data):
|
|
265
363
|
"""Process the output of a `Reader` that contains a map
|
|
266
|
-
configuration and
|
|
267
|
-
|
|
364
|
+
configuration and returns a NeXus NXentry object representing
|
|
365
|
+
the map.
|
|
268
366
|
|
|
269
367
|
:param data: Result of `Reader.read` where at least one item
|
|
270
368
|
has the value `'MapConfig'` for the `'schema'` key.
|
|
271
|
-
:type data:
|
|
272
|
-
:return: Map data
|
|
369
|
+
:type data: CHAP.pipeline.PipelineData
|
|
370
|
+
:return: Map data and metadata.
|
|
273
371
|
:rtype: nexusformat.nexus.NXentry
|
|
274
372
|
"""
|
|
275
|
-
|
|
276
373
|
map_config = self.get_config(data, 'common.models.map.MapConfig')
|
|
277
374
|
nxentry = self.__class__.get_nxentry(map_config)
|
|
278
375
|
|
|
@@ -280,29 +377,29 @@ class MapProcessor(Processor):
|
|
|
280
377
|
|
|
281
378
|
@staticmethod
|
|
282
379
|
def get_nxentry(map_config):
|
|
283
|
-
"""Use a `MapConfig` to construct a
|
|
284
|
-
`nexusformat.nexus.NXentry`
|
|
380
|
+
"""Use a `MapConfig` to construct a NeXus NXentry object.
|
|
285
381
|
|
|
286
|
-
:param map_config:
|
|
382
|
+
:param map_config: A valid map configuration.
|
|
287
383
|
:type map_config: MapConfig
|
|
288
|
-
:return:
|
|
289
|
-
structure
|
|
384
|
+
:return: The map's data and metadata contained in a NeXus
|
|
385
|
+
structure.
|
|
290
386
|
:rtype: nexusformat.nexus.NXentry
|
|
291
387
|
"""
|
|
292
|
-
|
|
293
|
-
from
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
388
|
+
# System modules
|
|
389
|
+
from json import dumps
|
|
390
|
+
|
|
391
|
+
# Third party modules
|
|
392
|
+
from nexusformat.nexus import (
|
|
393
|
+
NXcollection,
|
|
394
|
+
NXdata,
|
|
395
|
+
NXentry,
|
|
396
|
+
NXfield,
|
|
397
|
+
NXsample,
|
|
398
|
+
)
|
|
299
399
|
|
|
300
400
|
nxentry = NXentry(name=map_config.title)
|
|
301
|
-
|
|
302
401
|
nxentry.map_config = dumps(map_config.dict())
|
|
303
|
-
|
|
304
402
|
nxentry[map_config.sample.name] = NXsample(**map_config.sample.dict())
|
|
305
|
-
|
|
306
403
|
nxentry.attrs['station'] = map_config.station
|
|
307
404
|
|
|
308
405
|
nxentry.spec_scans = NXcollection()
|
|
@@ -313,7 +410,8 @@ class MapProcessor(Processor):
|
|
|
313
410
|
attrs={'spec_file': str(scans.spec_file)})
|
|
314
411
|
|
|
315
412
|
nxentry.data = NXdata()
|
|
316
|
-
|
|
413
|
+
if map_config.map_type == 'structured':
|
|
414
|
+
nxentry.data.attrs['axes'] = map_config.dims
|
|
317
415
|
for i, dim in enumerate(map_config.independent_dimensions[::-1]):
|
|
318
416
|
nxentry.data[dim.label] = NXfield(
|
|
319
417
|
value=map_config.coords[dim.label],
|
|
@@ -321,7 +419,8 @@ class MapProcessor(Processor):
|
|
|
321
419
|
attrs={'long_name': f'{dim.label} ({dim.units})',
|
|
322
420
|
'data_type': dim.data_type,
|
|
323
421
|
'local_name': dim.name})
|
|
324
|
-
|
|
422
|
+
if map_config.map_type == 'structured':
|
|
423
|
+
nxentry.data.attrs[f'{dim.label}_indices'] = i
|
|
325
424
|
|
|
326
425
|
signal = False
|
|
327
426
|
auxilliary_signals = []
|
|
@@ -350,22 +449,21 @@ class MapProcessor(Processor):
|
|
|
350
449
|
|
|
351
450
|
|
|
352
451
|
class NexusToNumpyProcessor(Processor):
|
|
353
|
-
"""A Processor to convert the default plottable data in
|
|
354
|
-
|
|
452
|
+
"""A Processor to convert the default plottable data in a NeXus
|
|
453
|
+
object into a `numpy.ndarray`.
|
|
355
454
|
"""
|
|
356
|
-
|
|
357
455
|
def process(self, data):
|
|
358
|
-
"""Return the default plottable data signal in
|
|
359
|
-
`numpy.ndarray`.
|
|
360
|
-
|
|
361
|
-
:param data:
|
|
362
|
-
:type data: nexusformat.nexus.
|
|
363
|
-
:raises ValueError:
|
|
364
|
-
signal
|
|
365
|
-
:return: default plottable data signal
|
|
456
|
+
"""Return the default plottable data signal in a NeXus object
|
|
457
|
+
contained in `data` as an `numpy.ndarray`.
|
|
458
|
+
|
|
459
|
+
:param data: Input data.
|
|
460
|
+
:type data: nexusformat.nexus.NXobject
|
|
461
|
+
:raises ValueError: If `data` has no default plottable data
|
|
462
|
+
signal.
|
|
463
|
+
:return: The default plottable data signal.
|
|
366
464
|
:rtype: numpy.ndarray
|
|
367
465
|
"""
|
|
368
|
-
|
|
466
|
+
# Third party modules
|
|
369
467
|
from nexusformat.nexus import NXdata
|
|
370
468
|
|
|
371
469
|
data = self.unwrap_pipelinedata(data)[-1]
|
|
@@ -392,22 +490,21 @@ class NexusToNumpyProcessor(Processor):
|
|
|
392
490
|
|
|
393
491
|
|
|
394
492
|
class NexusToXarrayProcessor(Processor):
|
|
395
|
-
"""A Processor to convert the default plottable data in
|
|
396
|
-
|
|
493
|
+
"""A Processor to convert the default plottable data in a
|
|
494
|
+
NeXus object into an `xarray.DataArray`.
|
|
397
495
|
"""
|
|
398
|
-
|
|
399
496
|
def process(self, data):
|
|
400
|
-
"""Return the default plottable data signal in
|
|
401
|
-
`xarray.DataArray`.
|
|
497
|
+
"""Return the default plottable data signal in a NeXus object
|
|
498
|
+
contained in `data` as an `xarray.DataArray`.
|
|
402
499
|
|
|
403
|
-
:param data:
|
|
404
|
-
:type data: nexusformat.nexus.
|
|
405
|
-
:raises ValueError:
|
|
500
|
+
:param data: Input data.
|
|
501
|
+
:type data: nexusformat.nexus.NXobject
|
|
502
|
+
:raises ValueError: If metadata for `xarray` is absent from
|
|
406
503
|
`data`
|
|
407
|
-
:return: default plottable data signal
|
|
504
|
+
:return: The default plottable data signal.
|
|
408
505
|
:rtype: xarray.DataArray
|
|
409
506
|
"""
|
|
410
|
-
|
|
507
|
+
# Third party modules
|
|
411
508
|
from nexusformat.nexus import NXdata
|
|
412
509
|
from xarray import DataArray
|
|
413
510
|
|
|
@@ -456,18 +553,15 @@ class PrintProcessor(Processor):
|
|
|
456
553
|
"""A Processor to simply print the input data to stdout and return
|
|
457
554
|
the original input data, unchanged in any way.
|
|
458
555
|
"""
|
|
459
|
-
|
|
460
556
|
def process(self, data):
|
|
461
557
|
"""Print and return the input data.
|
|
462
558
|
|
|
463
|
-
:param data: Input data
|
|
559
|
+
:param data: Input data.
|
|
464
560
|
:type data: object
|
|
465
561
|
:return: `data`
|
|
466
562
|
:rtype: object
|
|
467
563
|
"""
|
|
468
|
-
|
|
469
564
|
print(f'{self.__name__} data :')
|
|
470
|
-
|
|
471
565
|
if callable(getattr(data, '_str_tree', None)):
|
|
472
566
|
# If data is likely an NXobject, print its tree
|
|
473
567
|
# representation (since NXobjects' str representations are
|
|
@@ -480,23 +574,23 @@ class PrintProcessor(Processor):
|
|
|
480
574
|
|
|
481
575
|
|
|
482
576
|
class RawDetectorDataMapProcessor(Processor):
|
|
483
|
-
"""A Processor to return a map of raw derector data in
|
|
484
|
-
|
|
577
|
+
"""A Processor to return a map of raw derector data in a
|
|
578
|
+
NeXus NXroot object.
|
|
579
|
+
"""
|
|
485
580
|
def process(self, data, detector_name, detector_shape):
|
|
486
581
|
"""Process configurations for a map and return the raw
|
|
487
582
|
detector data data collected over the map.
|
|
488
583
|
|
|
489
|
-
:param data:
|
|
490
|
-
:type data:
|
|
491
|
-
:param detector_name: detector prefix
|
|
584
|
+
:param data: Input map configuration.
|
|
585
|
+
:type data: CHAP.pipeline.PipelineData
|
|
586
|
+
:param detector_name: The detector prefix.
|
|
492
587
|
:type detector_name: str
|
|
493
|
-
:param detector_shape: shape of detector data for a single
|
|
494
|
-
scan step
|
|
588
|
+
:param detector_shape: The shape of detector data for a single
|
|
589
|
+
scan step.
|
|
495
590
|
:type detector_shape: list
|
|
496
|
-
:return:
|
|
591
|
+
:return: Map of raw detector data.
|
|
497
592
|
:rtype: nexusformat.nexus.NXroot
|
|
498
593
|
"""
|
|
499
|
-
|
|
500
594
|
map_config = self.get_config(data)
|
|
501
595
|
nxroot = self.get_nxroot(map_config, detector_name, detector_shape)
|
|
502
596
|
|
|
@@ -504,17 +598,18 @@ class RawDetectorDataMapProcessor(Processor):
|
|
|
504
598
|
|
|
505
599
|
def get_config(self, data):
|
|
506
600
|
"""Get instances of the map configuration object needed by this
|
|
507
|
-
`Processor
|
|
601
|
+
`Processor`.
|
|
508
602
|
|
|
509
603
|
:param data: Result of `Reader.read` where at least one item
|
|
510
|
-
has the value `'MapConfig'` for the `'schema'` key
|
|
511
|
-
:type data:
|
|
604
|
+
has the value `'MapConfig'` for the `'schema'` key.
|
|
605
|
+
:type data: CHAP.pipeline.PipelineData
|
|
512
606
|
:raises Exception: If a valid map config object cannot be
|
|
513
607
|
constructed from `data`.
|
|
514
|
-
:return: valid
|
|
608
|
+
:return: A valid instance of the map configuration object with
|
|
515
609
|
field values taken from `data`.
|
|
516
610
|
:rtype: MapConfig
|
|
517
611
|
"""
|
|
612
|
+
# Local modules
|
|
518
613
|
from CHAP.common.models.map import MapConfig
|
|
519
614
|
|
|
520
615
|
map_config = False
|
|
@@ -532,27 +627,28 @@ class RawDetectorDataMapProcessor(Processor):
|
|
|
532
627
|
|
|
533
628
|
def get_nxroot(self, map_config, detector_name, detector_shape):
|
|
534
629
|
"""Get a map of the detector data collected by the scans in
|
|
535
|
-
`map_config`.The data will be returned along with some
|
|
630
|
+
`map_config`. The data will be returned along with some
|
|
536
631
|
relevant metadata in the form of a NeXus structure.
|
|
537
632
|
|
|
538
|
-
:param map_config:
|
|
633
|
+
:param map_config: The map configuration.
|
|
539
634
|
:type map_config: MapConfig
|
|
540
|
-
:param detector_name: detector prefix
|
|
635
|
+
:param detector_name: The detector prefix.
|
|
541
636
|
:type detector_name: str
|
|
542
|
-
:param detector_shape: shape of detector data for a single
|
|
543
|
-
scan step
|
|
637
|
+
:param detector_shape: The shape of detector data for a single
|
|
638
|
+
scan step.
|
|
544
639
|
:type detector_shape: list
|
|
545
|
-
:return:
|
|
640
|
+
:return: A map of the raw detector data.
|
|
546
641
|
:rtype: nexusformat.nexus.NXroot
|
|
547
642
|
"""
|
|
548
|
-
#
|
|
549
|
-
from nexusformat.nexus import (
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
643
|
+
# Third party modules
|
|
644
|
+
from nexusformat.nexus import (
|
|
645
|
+
NXdata,
|
|
646
|
+
NXdetector,
|
|
647
|
+
NXinstrument,
|
|
648
|
+
NXroot,
|
|
649
|
+
)
|
|
650
|
+
|
|
651
|
+
# Local modules
|
|
556
652
|
from CHAP.common import MapProcessor
|
|
557
653
|
|
|
558
654
|
nxroot = NXroot()
|
|
@@ -602,42 +698,39 @@ class RawDetectorDataMapProcessor(Processor):
|
|
|
602
698
|
|
|
603
699
|
|
|
604
700
|
class StrainAnalysisProcessor(Processor):
|
|
605
|
-
"""A Processor to compute a map of sample strains by fitting
|
|
701
|
+
"""A Processor to compute a map of sample strains by fitting Bragg
|
|
606
702
|
peaks in 1D detector data and analyzing the difference between
|
|
607
703
|
measured peak locations and expected peak locations for the sample
|
|
608
704
|
measured.
|
|
609
705
|
"""
|
|
610
|
-
|
|
611
706
|
def process(self, data):
|
|
612
707
|
"""Process the input map detector data & configuration for the
|
|
613
708
|
strain analysis procedure, and return a map of sample strains.
|
|
614
709
|
|
|
615
|
-
:param data:
|
|
710
|
+
:param data: Results of `MutlipleReader.read` containing input
|
|
616
711
|
map detector data and strain analysis configuration
|
|
617
|
-
:type data:
|
|
618
|
-
:return: map of sample strains
|
|
712
|
+
:type data: CHAP.pipeline.PipelineData
|
|
713
|
+
:return: A map of sample strains.
|
|
619
714
|
:rtype: xarray.Dataset
|
|
620
715
|
"""
|
|
621
|
-
|
|
622
716
|
strain_analysis_config = self.get_config(data)
|
|
623
717
|
|
|
624
718
|
return data
|
|
625
719
|
|
|
626
720
|
def get_config(self, data):
|
|
627
721
|
"""Get instances of the configuration objects needed by this
|
|
628
|
-
`Processor
|
|
722
|
+
`Processor`.
|
|
629
723
|
|
|
630
724
|
:param data: Result of `Reader.read` where at least one item
|
|
631
725
|
has the value `'StrainAnalysisConfig'` for the `'schema'`
|
|
632
726
|
key.
|
|
633
|
-
:type data:
|
|
727
|
+
:type data: CHAP.pipeline.PipelineData
|
|
634
728
|
:raises Exception: If valid config objects cannot be
|
|
635
729
|
constructed from `data`.
|
|
636
|
-
:return: valid
|
|
730
|
+
:return: A valid instance of the configuration object with
|
|
637
731
|
field values taken from `data`.
|
|
638
732
|
:rtype: StrainAnalysisConfig
|
|
639
733
|
"""
|
|
640
|
-
|
|
641
734
|
strain_analysis_config = False
|
|
642
735
|
if isinstance(data, list):
|
|
643
736
|
for item in data:
|
|
@@ -653,25 +746,25 @@ class StrainAnalysisProcessor(Processor):
|
|
|
653
746
|
|
|
654
747
|
|
|
655
748
|
class XarrayToNexusProcessor(Processor):
|
|
656
|
-
"""A Processor to convert the data in an `xarray` structure to
|
|
657
|
-
|
|
749
|
+
"""A Processor to convert the data in an `xarray` structure to a
|
|
750
|
+
NeXus NXdata object.
|
|
658
751
|
"""
|
|
659
|
-
|
|
660
752
|
def process(self, data):
|
|
661
|
-
"""Return `data` represented as
|
|
753
|
+
"""Return `data` represented as a NeXus NXdata object.
|
|
662
754
|
|
|
663
|
-
:param data: The input `xarray` structure
|
|
755
|
+
:param data: The input `xarray` structure.
|
|
664
756
|
:type data: typing.Union[xarray.DataArray, xarray.Dataset]
|
|
665
|
-
:return: The data and metadata in `data
|
|
757
|
+
:return: The data and metadata in `data`.
|
|
666
758
|
:rtype: nexusformat.nexus.NXdata
|
|
667
759
|
"""
|
|
668
|
-
|
|
669
|
-
from nexusformat.nexus import
|
|
760
|
+
# Third party modules
|
|
761
|
+
from nexusformat.nexus import (
|
|
762
|
+
NXdata,
|
|
763
|
+
NXfield,
|
|
764
|
+
)
|
|
670
765
|
|
|
671
766
|
data = self.unwrap_pipelinedata(data)[-1]
|
|
672
|
-
|
|
673
767
|
signal = NXfield(value=data.data, name=data.name, attrs=data.attrs)
|
|
674
|
-
|
|
675
768
|
axes = []
|
|
676
769
|
for name, coord in data.coords.items():
|
|
677
770
|
axes.append(
|
|
@@ -685,13 +778,12 @@ class XarrayToNumpyProcessor(Processor):
|
|
|
685
778
|
"""A Processor to convert the data in an `xarray.DataArray`
|
|
686
779
|
structure to an `numpy.ndarray`.
|
|
687
780
|
"""
|
|
688
|
-
|
|
689
781
|
def process(self, data):
|
|
690
782
|
"""Return just the signal values contained in `data`.
|
|
691
783
|
|
|
692
|
-
:param data: The input `xarray.DataArray
|
|
784
|
+
:param data: The input `xarray.DataArray`.
|
|
693
785
|
:type data: xarray.DataArray
|
|
694
|
-
:return: The data in `data
|
|
786
|
+
:return: The data in `data`.
|
|
695
787
|
:rtype: numpy.ndarray
|
|
696
788
|
"""
|
|
697
789
|
|
|
@@ -699,5 +791,7 @@ class XarrayToNumpyProcessor(Processor):
|
|
|
699
791
|
|
|
700
792
|
|
|
701
793
|
if __name__ == '__main__':
|
|
794
|
+
# Local modules
|
|
702
795
|
from CHAP.processor import main
|
|
796
|
+
|
|
703
797
|
main()
|