ChessAnalysisPipeline 0.0.12__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/processor.py +245 -153
- CHAP/common/reader.py +160 -124
- CHAP/common/writer.py +150 -94
- CHAP/tomo/models.py +10 -9
- CHAP/tomo/processor.py +554 -353
- CHAP/utils/general.py +21 -11
- CHAP/utils/scanparsers.py +78 -39
- {ChessAnalysisPipeline-0.0.12.dist-info → ChessAnalysisPipeline-0.0.13.dist-info}/METADATA +1 -1
- {ChessAnalysisPipeline-0.0.12.dist-info → ChessAnalysisPipeline-0.0.13.dist-info}/RECORD +15 -15
- {ChessAnalysisPipeline-0.0.12.dist-info → ChessAnalysisPipeline-0.0.13.dist-info}/WHEEL +1 -1
- {ChessAnalysisPipeline-0.0.12.dist-info → ChessAnalysisPipeline-0.0.13.dist-info}/LICENSE +0 -0
- {ChessAnalysisPipeline-0.0.12.dist-info → ChessAnalysisPipeline-0.0.13.dist-info}/entry_points.txt +0 -0
- {ChessAnalysisPipeline-0.0.12.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()
|
|
@@ -352,22 +449,21 @@ class MapProcessor(Processor):
|
|
|
352
449
|
|
|
353
450
|
|
|
354
451
|
class NexusToNumpyProcessor(Processor):
|
|
355
|
-
"""A Processor to convert the default plottable data in
|
|
356
|
-
|
|
452
|
+
"""A Processor to convert the default plottable data in a NeXus
|
|
453
|
+
object into a `numpy.ndarray`.
|
|
357
454
|
"""
|
|
358
|
-
|
|
359
455
|
def process(self, data):
|
|
360
|
-
"""Return the default plottable data signal in
|
|
361
|
-
`numpy.ndarray`.
|
|
362
|
-
|
|
363
|
-
:param data:
|
|
364
|
-
:type data: nexusformat.nexus.
|
|
365
|
-
:raises ValueError:
|
|
366
|
-
signal
|
|
367
|
-
: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.
|
|
368
464
|
:rtype: numpy.ndarray
|
|
369
465
|
"""
|
|
370
|
-
|
|
466
|
+
# Third party modules
|
|
371
467
|
from nexusformat.nexus import NXdata
|
|
372
468
|
|
|
373
469
|
data = self.unwrap_pipelinedata(data)[-1]
|
|
@@ -394,22 +490,21 @@ class NexusToNumpyProcessor(Processor):
|
|
|
394
490
|
|
|
395
491
|
|
|
396
492
|
class NexusToXarrayProcessor(Processor):
|
|
397
|
-
"""A Processor to convert the default plottable data in
|
|
398
|
-
|
|
493
|
+
"""A Processor to convert the default plottable data in a
|
|
494
|
+
NeXus object into an `xarray.DataArray`.
|
|
399
495
|
"""
|
|
400
|
-
|
|
401
496
|
def process(self, data):
|
|
402
|
-
"""Return the default plottable data signal in
|
|
403
|
-
`xarray.DataArray`.
|
|
497
|
+
"""Return the default plottable data signal in a NeXus object
|
|
498
|
+
contained in `data` as an `xarray.DataArray`.
|
|
404
499
|
|
|
405
|
-
:param data:
|
|
406
|
-
:type data: nexusformat.nexus.
|
|
407
|
-
:raises ValueError:
|
|
500
|
+
:param data: Input data.
|
|
501
|
+
:type data: nexusformat.nexus.NXobject
|
|
502
|
+
:raises ValueError: If metadata for `xarray` is absent from
|
|
408
503
|
`data`
|
|
409
|
-
:return: default plottable data signal
|
|
504
|
+
:return: The default plottable data signal.
|
|
410
505
|
:rtype: xarray.DataArray
|
|
411
506
|
"""
|
|
412
|
-
|
|
507
|
+
# Third party modules
|
|
413
508
|
from nexusformat.nexus import NXdata
|
|
414
509
|
from xarray import DataArray
|
|
415
510
|
|
|
@@ -458,18 +553,15 @@ class PrintProcessor(Processor):
|
|
|
458
553
|
"""A Processor to simply print the input data to stdout and return
|
|
459
554
|
the original input data, unchanged in any way.
|
|
460
555
|
"""
|
|
461
|
-
|
|
462
556
|
def process(self, data):
|
|
463
557
|
"""Print and return the input data.
|
|
464
558
|
|
|
465
|
-
:param data: Input data
|
|
559
|
+
:param data: Input data.
|
|
466
560
|
:type data: object
|
|
467
561
|
:return: `data`
|
|
468
562
|
:rtype: object
|
|
469
563
|
"""
|
|
470
|
-
|
|
471
564
|
print(f'{self.__name__} data :')
|
|
472
|
-
|
|
473
565
|
if callable(getattr(data, '_str_tree', None)):
|
|
474
566
|
# If data is likely an NXobject, print its tree
|
|
475
567
|
# representation (since NXobjects' str representations are
|
|
@@ -482,23 +574,23 @@ class PrintProcessor(Processor):
|
|
|
482
574
|
|
|
483
575
|
|
|
484
576
|
class RawDetectorDataMapProcessor(Processor):
|
|
485
|
-
"""A Processor to return a map of raw derector data in
|
|
486
|
-
|
|
577
|
+
"""A Processor to return a map of raw derector data in a
|
|
578
|
+
NeXus NXroot object.
|
|
579
|
+
"""
|
|
487
580
|
def process(self, data, detector_name, detector_shape):
|
|
488
581
|
"""Process configurations for a map and return the raw
|
|
489
582
|
detector data data collected over the map.
|
|
490
583
|
|
|
491
|
-
:param data:
|
|
492
|
-
:type data:
|
|
493
|
-
:param detector_name: detector prefix
|
|
584
|
+
:param data: Input map configuration.
|
|
585
|
+
:type data: CHAP.pipeline.PipelineData
|
|
586
|
+
:param detector_name: The detector prefix.
|
|
494
587
|
:type detector_name: str
|
|
495
|
-
:param detector_shape: shape of detector data for a single
|
|
496
|
-
scan step
|
|
588
|
+
:param detector_shape: The shape of detector data for a single
|
|
589
|
+
scan step.
|
|
497
590
|
:type detector_shape: list
|
|
498
|
-
:return:
|
|
591
|
+
:return: Map of raw detector data.
|
|
499
592
|
:rtype: nexusformat.nexus.NXroot
|
|
500
593
|
"""
|
|
501
|
-
|
|
502
594
|
map_config = self.get_config(data)
|
|
503
595
|
nxroot = self.get_nxroot(map_config, detector_name, detector_shape)
|
|
504
596
|
|
|
@@ -506,17 +598,18 @@ class RawDetectorDataMapProcessor(Processor):
|
|
|
506
598
|
|
|
507
599
|
def get_config(self, data):
|
|
508
600
|
"""Get instances of the map configuration object needed by this
|
|
509
|
-
`Processor
|
|
601
|
+
`Processor`.
|
|
510
602
|
|
|
511
603
|
:param data: Result of `Reader.read` where at least one item
|
|
512
|
-
has the value `'MapConfig'` for the `'schema'` key
|
|
513
|
-
:type data:
|
|
604
|
+
has the value `'MapConfig'` for the `'schema'` key.
|
|
605
|
+
:type data: CHAP.pipeline.PipelineData
|
|
514
606
|
:raises Exception: If a valid map config object cannot be
|
|
515
607
|
constructed from `data`.
|
|
516
|
-
:return: valid
|
|
608
|
+
:return: A valid instance of the map configuration object with
|
|
517
609
|
field values taken from `data`.
|
|
518
610
|
:rtype: MapConfig
|
|
519
611
|
"""
|
|
612
|
+
# Local modules
|
|
520
613
|
from CHAP.common.models.map import MapConfig
|
|
521
614
|
|
|
522
615
|
map_config = False
|
|
@@ -534,27 +627,28 @@ class RawDetectorDataMapProcessor(Processor):
|
|
|
534
627
|
|
|
535
628
|
def get_nxroot(self, map_config, detector_name, detector_shape):
|
|
536
629
|
"""Get a map of the detector data collected by the scans in
|
|
537
|
-
`map_config`.The data will be returned along with some
|
|
630
|
+
`map_config`. The data will be returned along with some
|
|
538
631
|
relevant metadata in the form of a NeXus structure.
|
|
539
632
|
|
|
540
|
-
:param map_config:
|
|
633
|
+
:param map_config: The map configuration.
|
|
541
634
|
:type map_config: MapConfig
|
|
542
|
-
:param detector_name: detector prefix
|
|
635
|
+
:param detector_name: The detector prefix.
|
|
543
636
|
:type detector_name: str
|
|
544
|
-
:param detector_shape: shape of detector data for a single
|
|
545
|
-
scan step
|
|
637
|
+
:param detector_shape: The shape of detector data for a single
|
|
638
|
+
scan step.
|
|
546
639
|
:type detector_shape: list
|
|
547
|
-
:return:
|
|
640
|
+
:return: A map of the raw detector data.
|
|
548
641
|
:rtype: nexusformat.nexus.NXroot
|
|
549
642
|
"""
|
|
550
|
-
#
|
|
551
|
-
from nexusformat.nexus import (
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
643
|
+
# Third party modules
|
|
644
|
+
from nexusformat.nexus import (
|
|
645
|
+
NXdata,
|
|
646
|
+
NXdetector,
|
|
647
|
+
NXinstrument,
|
|
648
|
+
NXroot,
|
|
649
|
+
)
|
|
650
|
+
|
|
651
|
+
# Local modules
|
|
558
652
|
from CHAP.common import MapProcessor
|
|
559
653
|
|
|
560
654
|
nxroot = NXroot()
|
|
@@ -604,42 +698,39 @@ class RawDetectorDataMapProcessor(Processor):
|
|
|
604
698
|
|
|
605
699
|
|
|
606
700
|
class StrainAnalysisProcessor(Processor):
|
|
607
|
-
"""A Processor to compute a map of sample strains by fitting
|
|
701
|
+
"""A Processor to compute a map of sample strains by fitting Bragg
|
|
608
702
|
peaks in 1D detector data and analyzing the difference between
|
|
609
703
|
measured peak locations and expected peak locations for the sample
|
|
610
704
|
measured.
|
|
611
705
|
"""
|
|
612
|
-
|
|
613
706
|
def process(self, data):
|
|
614
707
|
"""Process the input map detector data & configuration for the
|
|
615
708
|
strain analysis procedure, and return a map of sample strains.
|
|
616
709
|
|
|
617
|
-
:param data:
|
|
710
|
+
:param data: Results of `MutlipleReader.read` containing input
|
|
618
711
|
map detector data and strain analysis configuration
|
|
619
|
-
:type data:
|
|
620
|
-
:return: map of sample strains
|
|
712
|
+
:type data: CHAP.pipeline.PipelineData
|
|
713
|
+
:return: A map of sample strains.
|
|
621
714
|
:rtype: xarray.Dataset
|
|
622
715
|
"""
|
|
623
|
-
|
|
624
716
|
strain_analysis_config = self.get_config(data)
|
|
625
717
|
|
|
626
718
|
return data
|
|
627
719
|
|
|
628
720
|
def get_config(self, data):
|
|
629
721
|
"""Get instances of the configuration objects needed by this
|
|
630
|
-
`Processor
|
|
722
|
+
`Processor`.
|
|
631
723
|
|
|
632
724
|
:param data: Result of `Reader.read` where at least one item
|
|
633
725
|
has the value `'StrainAnalysisConfig'` for the `'schema'`
|
|
634
726
|
key.
|
|
635
|
-
:type data:
|
|
727
|
+
:type data: CHAP.pipeline.PipelineData
|
|
636
728
|
:raises Exception: If valid config objects cannot be
|
|
637
729
|
constructed from `data`.
|
|
638
|
-
:return: valid
|
|
730
|
+
:return: A valid instance of the configuration object with
|
|
639
731
|
field values taken from `data`.
|
|
640
732
|
:rtype: StrainAnalysisConfig
|
|
641
733
|
"""
|
|
642
|
-
|
|
643
734
|
strain_analysis_config = False
|
|
644
735
|
if isinstance(data, list):
|
|
645
736
|
for item in data:
|
|
@@ -655,25 +746,25 @@ class StrainAnalysisProcessor(Processor):
|
|
|
655
746
|
|
|
656
747
|
|
|
657
748
|
class XarrayToNexusProcessor(Processor):
|
|
658
|
-
"""A Processor to convert the data in an `xarray` structure to
|
|
659
|
-
|
|
749
|
+
"""A Processor to convert the data in an `xarray` structure to a
|
|
750
|
+
NeXus NXdata object.
|
|
660
751
|
"""
|
|
661
|
-
|
|
662
752
|
def process(self, data):
|
|
663
|
-
"""Return `data` represented as
|
|
753
|
+
"""Return `data` represented as a NeXus NXdata object.
|
|
664
754
|
|
|
665
|
-
:param data: The input `xarray` structure
|
|
755
|
+
:param data: The input `xarray` structure.
|
|
666
756
|
:type data: typing.Union[xarray.DataArray, xarray.Dataset]
|
|
667
|
-
:return: The data and metadata in `data
|
|
757
|
+
:return: The data and metadata in `data`.
|
|
668
758
|
:rtype: nexusformat.nexus.NXdata
|
|
669
759
|
"""
|
|
670
|
-
|
|
671
|
-
from nexusformat.nexus import
|
|
760
|
+
# Third party modules
|
|
761
|
+
from nexusformat.nexus import (
|
|
762
|
+
NXdata,
|
|
763
|
+
NXfield,
|
|
764
|
+
)
|
|
672
765
|
|
|
673
766
|
data = self.unwrap_pipelinedata(data)[-1]
|
|
674
|
-
|
|
675
767
|
signal = NXfield(value=data.data, name=data.name, attrs=data.attrs)
|
|
676
|
-
|
|
677
768
|
axes = []
|
|
678
769
|
for name, coord in data.coords.items():
|
|
679
770
|
axes.append(
|
|
@@ -687,13 +778,12 @@ class XarrayToNumpyProcessor(Processor):
|
|
|
687
778
|
"""A Processor to convert the data in an `xarray.DataArray`
|
|
688
779
|
structure to an `numpy.ndarray`.
|
|
689
780
|
"""
|
|
690
|
-
|
|
691
781
|
def process(self, data):
|
|
692
782
|
"""Return just the signal values contained in `data`.
|
|
693
783
|
|
|
694
|
-
:param data: The input `xarray.DataArray
|
|
784
|
+
:param data: The input `xarray.DataArray`.
|
|
695
785
|
:type data: xarray.DataArray
|
|
696
|
-
:return: The data in `data
|
|
786
|
+
:return: The data in `data`.
|
|
697
787
|
:rtype: numpy.ndarray
|
|
698
788
|
"""
|
|
699
789
|
|
|
@@ -701,5 +791,7 @@ class XarrayToNumpyProcessor(Processor):
|
|
|
701
791
|
|
|
702
792
|
|
|
703
793
|
if __name__ == '__main__':
|
|
794
|
+
# Local modules
|
|
704
795
|
from CHAP.processor import main
|
|
796
|
+
|
|
705
797
|
main()
|