ChessAnalysisPipeline 0.0.5__py3-none-any.whl → 0.0.6__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/TaskManager.py +214 -0
- CHAP/common/models/integration.py +392 -249
- CHAP/common/models/map.py +350 -198
- CHAP/common/processor.py +227 -189
- CHAP/common/reader.py +52 -39
- CHAP/common/utils/fit.py +1197 -991
- CHAP/common/utils/general.py +629 -372
- CHAP/common/utils/material.py +158 -121
- CHAP/common/utils/scanparsers.py +735 -339
- CHAP/common/writer.py +31 -25
- CHAP/edd/models.py +63 -49
- CHAP/edd/processor.py +130 -109
- CHAP/edd/reader.py +1 -1
- CHAP/edd/writer.py +1 -1
- CHAP/inference/processor.py +35 -28
- CHAP/inference/reader.py +1 -1
- CHAP/inference/writer.py +1 -1
- CHAP/pipeline.py +14 -28
- CHAP/processor.py +44 -75
- CHAP/reader.py +49 -40
- CHAP/runner.py +73 -32
- CHAP/saxswaxs/processor.py +1 -1
- CHAP/saxswaxs/reader.py +1 -1
- CHAP/saxswaxs/writer.py +1 -1
- CHAP/server.py +130 -0
- CHAP/sin2psi/processor.py +1 -1
- CHAP/sin2psi/reader.py +1 -1
- CHAP/sin2psi/writer.py +1 -1
- CHAP/tomo/__init__.py +1 -4
- CHAP/tomo/models.py +53 -31
- CHAP/tomo/processor.py +1326 -900
- CHAP/tomo/reader.py +4 -2
- CHAP/tomo/writer.py +4 -2
- CHAP/writer.py +47 -41
- {ChessAnalysisPipeline-0.0.5.dist-info → ChessAnalysisPipeline-0.0.6.dist-info}/METADATA +1 -1
- ChessAnalysisPipeline-0.0.6.dist-info/RECORD +52 -0
- ChessAnalysisPipeline-0.0.5.dist-info/RECORD +0 -50
- {ChessAnalysisPipeline-0.0.5.dist-info → ChessAnalysisPipeline-0.0.6.dist-info}/LICENSE +0 -0
- {ChessAnalysisPipeline-0.0.5.dist-info → ChessAnalysisPipeline-0.0.6.dist-info}/WHEEL +0 -0
- {ChessAnalysisPipeline-0.0.5.dist-info → ChessAnalysisPipeline-0.0.6.dist-info}/entry_points.txt +0 -0
- {ChessAnalysisPipeline-0.0.5.dist-info → ChessAnalysisPipeline-0.0.6.dist-info}/top_level.txt +0 -0
|
@@ -1,17 +1,8 @@
|
|
|
1
1
|
import copy
|
|
2
|
-
from functools import cache
|
|
3
|
-
import json
|
|
4
|
-
import logging
|
|
2
|
+
from functools import cache
|
|
5
3
|
import os
|
|
6
|
-
from time import time
|
|
7
4
|
from typing import Literal, Optional
|
|
8
5
|
|
|
9
|
-
# from multiprocessing.pool import ThreadPool
|
|
10
|
-
# from nexusformat.nexus import (NXdata,
|
|
11
|
-
# NXdetector,
|
|
12
|
-
# NXfield,
|
|
13
|
-
# NXprocess,
|
|
14
|
-
# NXroot)
|
|
15
6
|
import numpy as np
|
|
16
7
|
from pydantic import (BaseModel,
|
|
17
8
|
validator,
|
|
@@ -20,19 +11,15 @@ from pydantic import (BaseModel,
|
|
|
20
11
|
conint,
|
|
21
12
|
confloat,
|
|
22
13
|
FilePath)
|
|
23
|
-
#import pyFAI, pyFAI.multi_geometry, pyFAI.units
|
|
24
14
|
from pyFAI import load as pyfai_load
|
|
25
15
|
from pyFAI.multi_geometry import MultiGeometry
|
|
26
16
|
from pyFAI.units import AZIMUTHAL_UNITS, RADIAL_UNITS
|
|
27
|
-
#from pyspec.file.tiff import TiffFile
|
|
28
|
-
|
|
29
|
-
#from .map import MapConfig, SpecScans
|
|
30
17
|
|
|
31
18
|
|
|
32
19
|
class Detector(BaseModel):
|
|
33
|
-
"""
|
|
34
|
-
|
|
35
|
-
|
|
20
|
+
"""Detector class to represent a single detector used in the
|
|
21
|
+
experiment.
|
|
22
|
+
|
|
36
23
|
:param prefix: Prefix of the detector in the SPEC file.
|
|
37
24
|
:type prefix: str
|
|
38
25
|
:param poni_file: Path to the poni file.
|
|
@@ -43,11 +30,12 @@ class Detector(BaseModel):
|
|
|
43
30
|
prefix: constr(strip_whitespace=True, min_length=1)
|
|
44
31
|
poni_file: FilePath
|
|
45
32
|
mask_file: Optional[FilePath]
|
|
33
|
+
|
|
46
34
|
@validator('poni_file', allow_reuse=True)
|
|
47
35
|
def validate_poni_file(cls, poni_file):
|
|
48
|
-
"""
|
|
49
|
-
|
|
50
|
-
|
|
36
|
+
"""Validate the poni file by checking if it's a valid PONI
|
|
37
|
+
file.
|
|
38
|
+
|
|
51
39
|
:param poni_file: Path to the poni file.
|
|
52
40
|
:type poni_file: str
|
|
53
41
|
:raises ValueError: If poni_file is not a valid PONI file.
|
|
@@ -57,52 +45,79 @@ class Detector(BaseModel):
|
|
|
57
45
|
poni_file = os.path.abspath(poni_file)
|
|
58
46
|
try:
|
|
59
47
|
ai = azimuthal_integrator(poni_file)
|
|
60
|
-
except:
|
|
61
|
-
raise
|
|
62
|
-
|
|
63
|
-
|
|
48
|
+
except Exception as exc:
|
|
49
|
+
raise ValueError(f'{poni_file} is not a valid PONI file') from exc
|
|
50
|
+
return poni_file
|
|
51
|
+
|
|
64
52
|
@validator('mask_file', allow_reuse=True)
|
|
65
53
|
def validate_mask_file(cls, mask_file, values):
|
|
66
|
-
"""
|
|
67
|
-
|
|
68
|
-
|
|
54
|
+
"""Validate the mask file. If a mask file is provided, it
|
|
55
|
+
checks if it's a valid TIFF file.
|
|
56
|
+
|
|
69
57
|
:param mask_file: Path to the mask file.
|
|
70
58
|
:type mask_file: str or None
|
|
71
59
|
:param values: A dictionary of the Detector fields.
|
|
72
60
|
:type values: dict
|
|
73
|
-
:raises ValueError: If mask_file is provided and it's not a
|
|
61
|
+
:raises ValueError: If mask_file is provided and it's not a
|
|
62
|
+
valid TIFF file.
|
|
74
63
|
:raises ValueError: If `'poni_file'` is not provided in `values`.
|
|
75
64
|
:returns: Absolute path to the mask file or None.
|
|
76
|
-
:rtype: str or None
|
|
65
|
+
:rtype: str or None
|
|
77
66
|
"""
|
|
78
67
|
if mask_file is None:
|
|
79
|
-
return
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
68
|
+
return mask_file
|
|
69
|
+
|
|
70
|
+
mask_file = os.path.abspath(mask_file)
|
|
71
|
+
poni_file = values.get('poni_file')
|
|
72
|
+
if poni_file is None:
|
|
73
|
+
raise ValueError(
|
|
74
|
+
'Cannot validate mask file without a PONI file.')
|
|
75
|
+
try:
|
|
76
|
+
mask_array = get_mask_array(mask_file, poni_file)
|
|
77
|
+
except BaseException as exc:
|
|
78
|
+
raise ValueError(
|
|
79
|
+
f'Unable to open {mask_file} as a TIFF file') from exc
|
|
80
|
+
return mask_file
|
|
81
|
+
|
|
92
82
|
@property
|
|
93
83
|
def azimuthal_integrator(self):
|
|
94
|
-
|
|
84
|
+
"""Return the azimuthal integrator associated with this
|
|
85
|
+
detector.
|
|
86
|
+
"""
|
|
87
|
+
return azimuthal_integrator(self.poni_file)
|
|
88
|
+
|
|
95
89
|
@property
|
|
96
90
|
def mask_array(self):
|
|
97
|
-
|
|
91
|
+
"""Return the mask array assocated with this detector."""
|
|
92
|
+
return get_mask_array(self.mask_file, self.poni_file)
|
|
93
|
+
|
|
98
94
|
|
|
99
95
|
@cache
|
|
100
96
|
def azimuthal_integrator(poni_file:str):
|
|
97
|
+
"""Return the azimuthal integrator from a PONI file
|
|
98
|
+
|
|
99
|
+
:param poni_file: path to a PONI file
|
|
100
|
+
:type poni_file: str
|
|
101
|
+
:return: azimuthal integrator
|
|
102
|
+
:rtype: pyFAI.azimuthal_integrator.AzimuthalIntegrator
|
|
103
|
+
"""
|
|
101
104
|
if not isinstance(poni_file, str):
|
|
102
105
|
poni_file = str(poni_file)
|
|
103
|
-
return
|
|
106
|
+
return pyfai_load(poni_file)
|
|
107
|
+
|
|
108
|
+
|
|
104
109
|
@cache
|
|
105
110
|
def get_mask_array(mask_file:str, poni_file:str):
|
|
111
|
+
"""Return a mask array associated with a detector loaded from a
|
|
112
|
+
tiff file.
|
|
113
|
+
|
|
114
|
+
:param mask_file: path to a .tiff file
|
|
115
|
+
:type mask_file: str
|
|
116
|
+
:param poni_file: path to a PONI file
|
|
117
|
+
:type poni_file: str
|
|
118
|
+
:return: the mask array loaded from `mask_file`
|
|
119
|
+
:rtype: numpy.ndarray
|
|
120
|
+
"""
|
|
106
121
|
if mask_file is not None:
|
|
107
122
|
if not isinstance(mask_file, str):
|
|
108
123
|
mask_file = str(mask_file)
|
|
@@ -112,37 +127,46 @@ def get_mask_array(mask_file:str, poni_file:str):
|
|
|
112
127
|
mask_array = tiff.asarray()
|
|
113
128
|
else:
|
|
114
129
|
mask_array = np.zeros(azimuthal_integrator(poni_file).detector.shape)
|
|
115
|
-
return
|
|
130
|
+
return mask_array
|
|
131
|
+
|
|
116
132
|
|
|
117
133
|
class IntegrationConfig(BaseModel):
|
|
118
|
-
"""
|
|
119
|
-
|
|
134
|
+
"""Class representing the configuration for a raw detector data
|
|
135
|
+
integration.
|
|
120
136
|
|
|
121
|
-
:ivar tool_type: type of integration tool; always set to
|
|
137
|
+
:ivar tool_type: type of integration tool; always set to
|
|
138
|
+
"integration"
|
|
122
139
|
:type tool_type: str, optional
|
|
123
140
|
:ivar title: title of the integration
|
|
124
141
|
:type title: str
|
|
125
|
-
:ivar integration_type: type of integration, one of "azimuthal",
|
|
142
|
+
:ivar integration_type: type of integration, one of "azimuthal",
|
|
143
|
+
"radial", or "cake"
|
|
126
144
|
:type integration_type: str
|
|
127
145
|
:ivar detectors: list of detectors used in the integration
|
|
128
146
|
:type detectors: List[Detector]
|
|
129
|
-
:ivar radial_units: radial units for the integration, defaults to
|
|
147
|
+
:ivar radial_units: radial units for the integration, defaults to
|
|
148
|
+
`'q_A^-1'`
|
|
130
149
|
:type radial_units: str, optional
|
|
131
150
|
:ivar radial_min: minimum radial value for the integration range
|
|
132
151
|
:type radial_min: float, optional
|
|
133
152
|
:ivar radial_max: maximum radial value for the integration range
|
|
134
153
|
:type radial_max: float, optional
|
|
135
|
-
:ivar radial_npt: number of points in the radial range for the
|
|
154
|
+
:ivar radial_npt: number of points in the radial range for the
|
|
155
|
+
integration
|
|
136
156
|
:type radial_npt: int, optional
|
|
137
157
|
:ivar azimuthal_units: azimuthal units for the integration
|
|
138
158
|
:type azimuthal_units: str, optional
|
|
139
|
-
:ivar azimuthal_min: minimum azimuthal value for the integration
|
|
159
|
+
:ivar azimuthal_min: minimum azimuthal value for the integration
|
|
160
|
+
range
|
|
140
161
|
:type azimuthal_min: float, optional
|
|
141
|
-
:ivar azimuthal_max: maximum azimuthal value for the integration
|
|
162
|
+
:ivar azimuthal_max: maximum azimuthal value for the integration
|
|
163
|
+
range
|
|
142
164
|
:type azimuthal_max: float, optional
|
|
143
|
-
:ivar azimuthal_npt: number of points in the azimuthal range for
|
|
165
|
+
:ivar azimuthal_npt: number of points in the azimuthal range for
|
|
166
|
+
the integration
|
|
144
167
|
:type azimuthal_npt: int, optional
|
|
145
|
-
:ivar error_model: error model for the integration, one of
|
|
168
|
+
:ivar error_model: error model for the integration, one of
|
|
169
|
+
"poisson" or "azimuthal"
|
|
146
170
|
:type error_model: str, optional
|
|
147
171
|
"""
|
|
148
172
|
tool_type: Literal['integration'] = 'integration'
|
|
@@ -159,71 +183,95 @@ class IntegrationConfig(BaseModel):
|
|
|
159
183
|
azimuthal_npt: conint(gt=0) = 3600
|
|
160
184
|
error_model: Optional[Literal['poisson', 'azimuthal']]
|
|
161
185
|
sequence_index: Optional[conint(gt=0)]
|
|
186
|
+
|
|
162
187
|
@validator('radial_units', allow_reuse=True)
|
|
163
188
|
def validate_radial_units(cls, radial_units):
|
|
164
|
-
"""
|
|
165
|
-
Validate the radial units for the integration.
|
|
189
|
+
"""Validate the radial units for the integration.
|
|
166
190
|
|
|
167
|
-
:param radial_units: unvalidated radial units for the
|
|
191
|
+
:param radial_units: unvalidated radial units for the
|
|
192
|
+
integration
|
|
168
193
|
:type radial_units: str
|
|
169
|
-
:raises ValueError: if radial units are not one of the
|
|
194
|
+
:raises ValueError: if radial units are not one of the
|
|
195
|
+
recognized radial units
|
|
170
196
|
:return: validated radial units
|
|
171
197
|
:rtype: str
|
|
172
198
|
"""
|
|
173
199
|
if radial_units in RADIAL_UNITS.keys():
|
|
174
|
-
return
|
|
175
|
-
|
|
176
|
-
|
|
200
|
+
return radial_units
|
|
201
|
+
raise ValueError(
|
|
202
|
+
f'Invalid radial units: {radial_units}. '
|
|
203
|
+
f'Must be one of {", ".join(RADIAL_UNITS.keys())}')
|
|
204
|
+
|
|
177
205
|
@validator('azimuthal_units', allow_reuse=True)
|
|
178
206
|
def validate_azimuthal_units(cls, azimuthal_units):
|
|
179
|
-
"""
|
|
180
|
-
Validate that `azimuthal_units` is one of the keys in the
|
|
207
|
+
"""Validate that `azimuthal_units` is one of the keys in the
|
|
181
208
|
`pyFAI.units.AZIMUTHAL_UNITS` dictionary.
|
|
182
209
|
|
|
183
|
-
:param azimuthal_units: The string representing the unit to be
|
|
210
|
+
:param azimuthal_units: The string representing the unit to be
|
|
211
|
+
validated.
|
|
184
212
|
:type azimuthal_units: str
|
|
185
|
-
:raises ValueError: If `azimuthal_units` is not one of the
|
|
186
|
-
|
|
213
|
+
:raises ValueError: If `azimuthal_units` is not one of the
|
|
214
|
+
keys in `pyFAI.units.AZIMUTHAL_UNITS`
|
|
215
|
+
:return: The original supplied value, if is one of the keys in
|
|
216
|
+
`pyFAI.units.AZIMUTHAL_UNITS`.
|
|
187
217
|
:rtype: str
|
|
188
218
|
"""
|
|
189
219
|
if azimuthal_units in AZIMUTHAL_UNITS.keys():
|
|
190
|
-
return
|
|
191
|
-
|
|
192
|
-
|
|
220
|
+
return azimuthal_units
|
|
221
|
+
raise ValueError(
|
|
222
|
+
f'Invalid azimuthal units: {azimuthal_units}. '
|
|
223
|
+
f'Must be one of {", ".join(AZIMUTHAL_UNITS.keys())}')
|
|
224
|
+
|
|
193
225
|
def validate_range_max(range_name:str):
|
|
194
226
|
"""Validate the maximum value of an integration range.
|
|
195
227
|
|
|
196
|
-
:param range_name: The name of the integration range
|
|
228
|
+
:param range_name: The name of the integration range
|
|
229
|
+
(e.g. radial, azimuthal).
|
|
197
230
|
:type range_name: str
|
|
198
231
|
:return: The callable that performs the validation.
|
|
199
232
|
:rtype: callable
|
|
200
233
|
"""
|
|
201
234
|
def _validate_range_max(cls, range_max, values):
|
|
202
|
-
"""Check if the maximum value of the integration range is
|
|
235
|
+
"""Check if the maximum value of the integration range is
|
|
236
|
+
greater than its minimum value.
|
|
203
237
|
|
|
204
|
-
:param range_max: The maximum value of the integration
|
|
238
|
+
:param range_max: The maximum value of the integration
|
|
239
|
+
range.
|
|
205
240
|
:type range_max: float
|
|
206
|
-
:param values: The values of the other fields being
|
|
241
|
+
:param values: The values of the other fields being
|
|
242
|
+
validated.
|
|
207
243
|
:type values: dict
|
|
208
|
-
:raises ValueError: If the maximum value of the
|
|
244
|
+
:raises ValueError: If the maximum value of the
|
|
245
|
+
integration range is not greater than its minimum
|
|
246
|
+
value.
|
|
209
247
|
:return: The validated maximum range value
|
|
210
248
|
:rtype: float
|
|
211
249
|
"""
|
|
212
250
|
range_min = values.get(f'{range_name}_min')
|
|
213
251
|
if range_min < range_max:
|
|
214
|
-
return
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
252
|
+
return range_max
|
|
253
|
+
raise ValueError(
|
|
254
|
+
'Maximum value of integration range must be '
|
|
255
|
+
'greater than minimum value of integration range '
|
|
256
|
+
f'({range_name}_min={range_min}).')
|
|
257
|
+
return _validate_range_max
|
|
258
|
+
|
|
259
|
+
_validate_radial_max = validator(
|
|
260
|
+
'radial_max',
|
|
261
|
+
allow_reuse=True)(validate_range_max('radial'))
|
|
262
|
+
_validate_azimuthal_max = validator(
|
|
263
|
+
'azimuthal_max',
|
|
264
|
+
allow_reuse=True)(validate_range_max('azimuthal'))
|
|
265
|
+
|
|
220
266
|
def validate_for_map_config(self, map_config:BaseModel):
|
|
221
|
-
"""
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
:param map_config: The `MapConfig` instance to validate
|
|
267
|
+
"""Validate the existence of the detector data file for all
|
|
268
|
+
scan points in `map_config`.
|
|
269
|
+
|
|
270
|
+
:param map_config: The `MapConfig` instance to validate
|
|
271
|
+
against.
|
|
225
272
|
:type map_config: MapConfig
|
|
226
|
-
:raises RuntimeError: If a detector data file could not be
|
|
273
|
+
:raises RuntimeError: If a detector data file could not be
|
|
274
|
+
found for a scan point occurring in `map_config`.
|
|
227
275
|
:return: None
|
|
228
276
|
:rtype: None
|
|
229
277
|
"""
|
|
@@ -232,39 +280,55 @@ class IntegrationConfig(BaseModel):
|
|
|
232
280
|
for scan_number in scans.scan_numbers:
|
|
233
281
|
scanparser = scans.get_scanparser(scan_number)
|
|
234
282
|
for scan_step_index in range(scanparser.spec_scan_npts):
|
|
235
|
-
# Make sure the detector data file exists for
|
|
283
|
+
# Make sure the detector data file exists for
|
|
284
|
+
# all scan points
|
|
236
285
|
try:
|
|
237
|
-
detector_data_file =
|
|
238
|
-
|
|
239
|
-
|
|
286
|
+
detector_data_file = \
|
|
287
|
+
scanparser.get_detector_data_file(
|
|
288
|
+
detector.prefix, scan_step_index)
|
|
289
|
+
except Exception as exc:
|
|
290
|
+
raise RuntimeError(
|
|
291
|
+
'Could not find data file for detector prefix '
|
|
292
|
+
f'{detector.prefix} '
|
|
293
|
+
f'on scan number {scan_number} '
|
|
294
|
+
f'in spec file {scans.spec_file}') from exc
|
|
295
|
+
|
|
240
296
|
def get_azimuthal_adjustments(self):
|
|
241
|
-
"""To enable a continuous range of integration in the
|
|
242
|
-
for radial and cake integration, obtain
|
|
243
|
-
`IntegrationConfig`'s `azimuthal_min`
|
|
244
|
-
angle amount by which those
|
|
245
|
-
|
|
297
|
+
"""To enable a continuous range of integration in the
|
|
298
|
+
azimuthal direction for radial and cake integration, obtain
|
|
299
|
+
adjusted values for this `IntegrationConfig`'s `azimuthal_min`
|
|
300
|
+
and `azimuthal_max` values, the angle amount by which those
|
|
301
|
+
values were adjusted, and the proper location of the
|
|
302
|
+
discontinuity in the azimuthal direction.
|
|
246
303
|
|
|
247
|
-
:return: Adjusted chi_min, adjusted chi_max, chi_offset,
|
|
304
|
+
:return: Adjusted chi_min, adjusted chi_max, chi_offset,
|
|
305
|
+
chi_discontinuity
|
|
248
306
|
:rtype: tuple[float,float,float,float]
|
|
249
307
|
"""
|
|
250
|
-
return
|
|
308
|
+
return get_azimuthal_adjustments(self.azimuthal_min,
|
|
309
|
+
self.azimuthal_max)
|
|
310
|
+
|
|
251
311
|
def get_azimuthal_integrators(self):
|
|
252
|
-
"""Get a list of `AzimuthalIntegrator`s that correspond to the
|
|
253
|
-
configurations in this instance of
|
|
312
|
+
"""Get a list of `AzimuthalIntegrator`s that correspond to the
|
|
313
|
+
detector configurations in this instance of
|
|
314
|
+
`IntegrationConfig`.
|
|
254
315
|
|
|
255
|
-
The returned `AzimuthalIntegrator`s are (if need be)
|
|
256
|
-
in the azimuthal direction to achieve a
|
|
257
|
-
in the azimuthal direction.
|
|
316
|
+
The returned `AzimuthalIntegrator`s are (if need be)
|
|
317
|
+
artificially rotated in the azimuthal direction to achieve a
|
|
318
|
+
continuous range of integration in the azimuthal direction.
|
|
258
319
|
|
|
259
|
-
:returns: A list of `AzimuthalIntegrator`s appropriate for use
|
|
260
|
-
`IntegrationConfig` tool
|
|
320
|
+
:returns: A list of `AzimuthalIntegrator`s appropriate for use
|
|
321
|
+
by this `IntegrationConfig` tool
|
|
261
322
|
:rtype: list[pyFAI.azimuthalIntegrator.AzimuthalIntegrator]
|
|
262
323
|
"""
|
|
263
|
-
|
|
264
|
-
return
|
|
324
|
+
chi_offset = self.get_azimuthal_adjustments()[2]
|
|
325
|
+
return get_azimuthal_integrators(
|
|
326
|
+
tuple([detector.poni_file for detector in self.detectors]),
|
|
327
|
+
chi_offset=chi_offset)
|
|
328
|
+
|
|
265
329
|
def get_multi_geometry_integrator(self):
|
|
266
|
-
"""Get a `MultiGeometry` integrator suitable for use by this
|
|
267
|
-
`IntegrationConfig`.
|
|
330
|
+
"""Get a `MultiGeometry` integrator suitable for use by this
|
|
331
|
+
instance of `IntegrationConfig`.
|
|
268
332
|
|
|
269
333
|
:return: A `MultiGeometry` integrator
|
|
270
334
|
:rtype: pyFAI.multi_geometry.MultiGeometry
|
|
@@ -272,94 +336,138 @@ class IntegrationConfig(BaseModel):
|
|
|
272
336
|
poni_files = tuple([detector.poni_file for detector in self.detectors])
|
|
273
337
|
radial_range = (self.radial_min, self.radial_max)
|
|
274
338
|
azimuthal_range = (self.azimuthal_min, self.azimuthal_max)
|
|
275
|
-
return
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
339
|
+
return get_multi_geometry_integrator(poni_files, self.radial_units,
|
|
340
|
+
radial_range, azimuthal_range)
|
|
341
|
+
|
|
342
|
+
def get_azimuthally_integrated_data(self,
|
|
343
|
+
spec_scans:BaseModel,
|
|
344
|
+
scan_number:int,
|
|
345
|
+
scan_step_index:int):
|
|
346
|
+
"""Return azimuthally-integrated data for the scan step
|
|
347
|
+
specified.
|
|
348
|
+
|
|
349
|
+
:param spec_scans: An instance of `SpecScans` containing the
|
|
350
|
+
scan step requested.
|
|
280
351
|
:type spec_scans: SpecScans
|
|
281
|
-
:param scan_number: The number of the scan containing the scan
|
|
352
|
+
:param scan_number: The number of the scan containing the scan
|
|
353
|
+
step requested.
|
|
282
354
|
:type scan_number: int
|
|
283
355
|
:param scan_step_index: The index of the scan step requested.
|
|
284
356
|
:type scan_step_index: int
|
|
285
|
-
:return: A 1D array of azimuthally-integrated raw detector
|
|
357
|
+
:return: A 1D array of azimuthally-integrated raw detector
|
|
358
|
+
intensities.
|
|
286
359
|
:rtype: np.ndarray
|
|
287
360
|
"""
|
|
288
|
-
detector_data = spec_scans.get_detector_data(self.detectors,
|
|
361
|
+
detector_data = spec_scans.get_detector_data(self.detectors,
|
|
362
|
+
scan_number,
|
|
363
|
+
scan_step_index)
|
|
289
364
|
integrator = self.get_multi_geometry_integrator()
|
|
290
365
|
lst_mask = [detector.mask_array for detector in self.detectors]
|
|
291
|
-
result = integrator.integrate1d(detector_data,
|
|
366
|
+
result = integrator.integrate1d(detector_data,
|
|
367
|
+
lst_mask=lst_mask,
|
|
368
|
+
npt=self.radial_npt,
|
|
369
|
+
error_model=self.error_model)
|
|
292
370
|
if result.sigma is None:
|
|
293
|
-
return
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
def get_radially_integrated_data(self,
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
371
|
+
return result.intensity
|
|
372
|
+
return result.intensity, result.sigma
|
|
373
|
+
|
|
374
|
+
def get_radially_integrated_data(self,
|
|
375
|
+
spec_scans:BaseModel,
|
|
376
|
+
scan_number:int,
|
|
377
|
+
scan_step_index:int):
|
|
378
|
+
"""Return radially-integrated data for the scan step
|
|
379
|
+
specified.
|
|
380
|
+
|
|
381
|
+
:param spec_scans: An instance of `SpecScans` containing the
|
|
382
|
+
scan step requested.
|
|
300
383
|
:type spec_scans: SpecScans
|
|
301
|
-
:param scan_number: The number of the scan containing the scan
|
|
384
|
+
:param scan_number: The number of the scan containing the scan
|
|
385
|
+
step requested.
|
|
302
386
|
:type scan_number: int
|
|
303
387
|
:param scan_step_index: The index of the scan step requested.
|
|
304
388
|
:type scan_step_index: int
|
|
305
|
-
:return: A 1D array of radially-integrated raw detector
|
|
389
|
+
:return: A 1D array of radially-integrated raw detector
|
|
390
|
+
intensities.
|
|
306
391
|
:rtype: np.ndarray
|
|
307
392
|
"""
|
|
308
|
-
# Handle idiosyncracies of azimuthal ranges in pyFAI
|
|
309
|
-
#
|
|
310
|
-
chi_min, chi_max,
|
|
393
|
+
# Handle idiosyncracies of azimuthal ranges in pyFAI Adjust
|
|
394
|
+
# chi ranges to get a continuous range of iintegrated data
|
|
395
|
+
chi_min, chi_max, *adjust = self.get_azimuthal_adjustments()
|
|
311
396
|
# Perform radial integration on a detector-by-detector basis.
|
|
312
|
-
|
|
397
|
+
intensity_each_detector = []
|
|
313
398
|
variance_each_detector = []
|
|
314
399
|
integrators = self.get_azimuthal_integrators()
|
|
315
|
-
for
|
|
316
|
-
detector_data = spec_scans.get_detector_data(
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
400
|
+
for integrator, detector in zip(integrators, self.detectors):
|
|
401
|
+
detector_data = spec_scans.get_detector_data(
|
|
402
|
+
[detector], scan_number, scan_step_index)[0]
|
|
403
|
+
result = integrator.integrate_radial(
|
|
404
|
+
detector_data,
|
|
405
|
+
self.azimuthal_npt,
|
|
406
|
+
unit=self.azimuthal_units,
|
|
407
|
+
azimuth_range=(chi_min, chi_max),
|
|
408
|
+
radial_unit=self.radial_units,
|
|
409
|
+
radial_range=(self.radial_min, self.radial_max),
|
|
410
|
+
mask=detector.mask_array) # , error_model=self.error_model)
|
|
411
|
+
intensity_each_detector.append(result.intensity)
|
|
322
412
|
if result.sigma is not None:
|
|
323
413
|
variance_each_detector.append(result.sigma**2)
|
|
324
|
-
# Add the individual detectors' integrated intensities
|
|
325
|
-
|
|
414
|
+
# Add the individual detectors' integrated intensities
|
|
415
|
+
# together
|
|
416
|
+
intensity = np.nansum(intensity_each_detector, axis=0)
|
|
326
417
|
# Ignore data at values of chi for which there was no data
|
|
327
|
-
|
|
328
|
-
if len(
|
|
329
|
-
return
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
418
|
+
intensity = np.where(intensity == 0, np.nan, intensity)
|
|
419
|
+
if len(intensity_each_detector) != len(variance_each_detector):
|
|
420
|
+
return intensity
|
|
421
|
+
|
|
422
|
+
# Get the standard deviation of the summed detectors'
|
|
423
|
+
# intensities
|
|
424
|
+
sigma = np.sqrt(np.nansum(variance_each_detector, axis=0))
|
|
425
|
+
return intensity, sigma
|
|
426
|
+
|
|
427
|
+
def get_cake_integrated_data(self,
|
|
428
|
+
spec_scans:BaseModel,
|
|
429
|
+
scan_number:int,
|
|
430
|
+
scan_step_index:int):
|
|
335
431
|
"""Return cake-integrated data for the scan step specified.
|
|
336
|
-
|
|
337
|
-
:param spec_scans: An instance of `SpecScans` containing the
|
|
432
|
+
|
|
433
|
+
:param spec_scans: An instance of `SpecScans` containing the
|
|
434
|
+
scan step requested.
|
|
338
435
|
:type spec_scans: SpecScans
|
|
339
|
-
:param scan_number: The number of the scan containing the scan
|
|
436
|
+
:param scan_number: The number of the scan containing the scan
|
|
437
|
+
step requested.
|
|
340
438
|
:type scan_number: int
|
|
341
439
|
:param scan_step_index: The index of the scan step requested.
|
|
342
440
|
:type scan_step_index: int
|
|
343
|
-
:return: A 2D array of cake-integrated raw detector
|
|
441
|
+
:return: A 2D array of cake-integrated raw detector
|
|
442
|
+
intensities.
|
|
344
443
|
:rtype: np.ndarray
|
|
345
444
|
"""
|
|
346
|
-
detector_data = spec_scans.get_detector_data(
|
|
445
|
+
detector_data = spec_scans.get_detector_data(
|
|
446
|
+
self.detectors, scan_number, scan_step_index)
|
|
347
447
|
integrator = self.get_multi_geometry_integrator()
|
|
348
448
|
lst_mask = [detector.mask_array for detector in self.detectors]
|
|
349
|
-
result = integrator.integrate2d(
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
449
|
+
result = integrator.integrate2d(
|
|
450
|
+
detector_data,
|
|
451
|
+
lst_mask=lst_mask,
|
|
452
|
+
npt_rad=self.radial_npt,
|
|
453
|
+
npt_azim=self.azimuthal_npt,
|
|
454
|
+
method='bbox',
|
|
455
|
+
error_model=self.error_model)
|
|
353
456
|
if result.sigma is None:
|
|
354
|
-
return
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
def get_integrated_data(self,
|
|
457
|
+
return result.intensity
|
|
458
|
+
return result.intensity, result.sigma
|
|
459
|
+
|
|
460
|
+
def get_integrated_data(self,
|
|
461
|
+
spec_scans:BaseModel,
|
|
462
|
+
scan_number:int,
|
|
463
|
+
scan_step_index:int):
|
|
358
464
|
"""Return integrated data for the scan step specified.
|
|
359
|
-
|
|
360
|
-
:param spec_scans: An instance of `SpecScans` containing the
|
|
465
|
+
|
|
466
|
+
:param spec_scans: An instance of `SpecScans` containing the
|
|
467
|
+
scan step requested.
|
|
361
468
|
:type spec_scans: SpecScans
|
|
362
|
-
:param scan_number: The number of the scan containing the scan
|
|
469
|
+
:param scan_number: The number of the scan containing the scan
|
|
470
|
+
step requested.
|
|
363
471
|
:type scan_number: int
|
|
364
472
|
:param scan_step_index: The index of the scan step requested.
|
|
365
473
|
:type scan_step_index: int
|
|
@@ -367,84 +475,106 @@ class IntegrationConfig(BaseModel):
|
|
|
367
475
|
:rtype: np.ndarray
|
|
368
476
|
"""
|
|
369
477
|
if self.integration_type == 'azimuthal':
|
|
370
|
-
return
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
return
|
|
478
|
+
return self.get_azimuthally_integrated_data(spec_scans,
|
|
479
|
+
scan_number,
|
|
480
|
+
scan_step_index)
|
|
481
|
+
if self.integration_type == 'radial':
|
|
482
|
+
return self.get_radially_integrated_data(spec_scans,
|
|
483
|
+
scan_number,
|
|
484
|
+
scan_step_index)
|
|
485
|
+
if self.integration_type == 'cake':
|
|
486
|
+
return self.get_cake_integrated_data(spec_scans,
|
|
487
|
+
scan_number,
|
|
488
|
+
scan_step_index)
|
|
489
|
+
return None
|
|
375
490
|
|
|
376
491
|
@property
|
|
377
492
|
def integrated_data_coordinates(self):
|
|
378
|
-
"""
|
|
379
|
-
|
|
380
|
-
of
|
|
381
|
-
|
|
382
|
-
:return: A dictionary with either one or two keys: 'azimuthal'
|
|
383
|
-
'radial', each of which points to a 1-D `numpy`
|
|
384
|
-
values.
|
|
493
|
+
"""Return a dictionary of coordinate arrays for navigating the
|
|
494
|
+
dimension(s) of the integrated data produced by this instance
|
|
495
|
+
of `IntegrationConfig`.
|
|
496
|
+
|
|
497
|
+
:return: A dictionary with either one or two keys: 'azimuthal'
|
|
498
|
+
and/or 'radial', each of which points to a 1-D `numpy`
|
|
499
|
+
array of coordinate values.
|
|
385
500
|
:rtype: dict[str,np.ndarray]
|
|
386
501
|
"""
|
|
387
502
|
if self.integration_type == 'azimuthal':
|
|
388
|
-
return
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
503
|
+
return get_integrated_data_coordinates(
|
|
504
|
+
radial_range=(self.radial_min, self.radial_max),
|
|
505
|
+
radial_npt=self.radial_npt)
|
|
506
|
+
if self.integration_type == 'radial':
|
|
507
|
+
return get_integrated_data_coordinates(
|
|
508
|
+
azimuthal_range=(self.azimuthal_min, self.azimuthal_max),
|
|
509
|
+
azimuthal_npt=self.azimuthal_npt)
|
|
510
|
+
if self.integration_type == 'cake':
|
|
511
|
+
return get_integrated_data_coordinates(
|
|
512
|
+
radial_range=(self.radial_min, self.radial_max),
|
|
513
|
+
radial_npt=self.radial_npt,
|
|
514
|
+
azimuthal_range=(self.azimuthal_min, self.azimuthal_max),
|
|
515
|
+
azimuthal_npt=self.azimuthal_npt)
|
|
516
|
+
return None
|
|
517
|
+
|
|
398
518
|
@property
|
|
399
519
|
def integrated_data_dims(self):
|
|
400
|
-
"""Return a tuple of the coordinate labels for the integrated
|
|
401
|
-
produced by this instance of `IntegrationConfig`.
|
|
520
|
+
"""Return a tuple of the coordinate labels for the integrated
|
|
521
|
+
data produced by this instance of `IntegrationConfig`.
|
|
402
522
|
"""
|
|
403
523
|
directions = list(self.integrated_data_coordinates.keys())
|
|
404
|
-
dim_names = [getattr(self, f'{direction}_units')
|
|
405
|
-
|
|
524
|
+
dim_names = [getattr(self, f'{direction}_units')
|
|
525
|
+
for direction in directions]
|
|
526
|
+
return dim_names
|
|
527
|
+
|
|
406
528
|
@property
|
|
407
529
|
def integrated_data_shape(self):
|
|
408
|
-
"""Return a tuple representing the shape of the integrated
|
|
409
|
-
produced by this instance of `IntegrationConfig` for a
|
|
530
|
+
"""Return a tuple representing the shape of the integrated
|
|
531
|
+
data produced by this instance of `IntegrationConfig` for a
|
|
532
|
+
single scan step.
|
|
410
533
|
"""
|
|
411
|
-
return
|
|
534
|
+
return tuple([len(coordinate_values)
|
|
535
|
+
for coordinate_name, coordinate_values
|
|
536
|
+
in self.integrated_data_coordinates.items()])
|
|
537
|
+
|
|
412
538
|
|
|
413
539
|
@cache
|
|
414
540
|
def get_azimuthal_adjustments(chi_min:float, chi_max:float):
|
|
415
|
-
"""
|
|
416
|
-
|
|
417
|
-
offset, and discontinuty.
|
|
541
|
+
"""Fix chi discontinuity at 180 degrees and return the adjusted
|
|
542
|
+
chi range, offset, and discontinuty.
|
|
418
543
|
|
|
419
|
-
If the discontinuity is crossed, obtain the offset to artificially
|
|
420
|
-
detectors to achieve a continuous azimuthal integration
|
|
544
|
+
If the discontinuity is crossed, obtain the offset to artificially
|
|
545
|
+
rotate detectors to achieve a continuous azimuthal integration
|
|
546
|
+
range.
|
|
421
547
|
|
|
422
548
|
:param chi_min: The minimum value of the azimuthal range.
|
|
423
549
|
:type chi_min: float
|
|
424
550
|
:param chi_max: The maximum value of the azimuthal range.
|
|
425
551
|
:type chi_max: float
|
|
426
|
-
:return: The following four values: the adjusted minimum value of
|
|
427
|
-
azimuthal range, the adjusted maximum value of the
|
|
428
|
-
value by which the chi angle was
|
|
429
|
-
discontinuity.
|
|
552
|
+
:return: The following four values: the adjusted minimum value of
|
|
553
|
+
the azimuthal range, the adjusted maximum value of the
|
|
554
|
+
azimuthal range, the value by which the chi angle was
|
|
555
|
+
adjusted, the position of the chi discontinuity.
|
|
430
556
|
"""
|
|
431
557
|
# Fix chi discontinuity at 180 degrees for now.
|
|
432
558
|
chi_disc = 180
|
|
433
|
-
# If the discontinuity is crossed, artificially rotate the
|
|
434
|
-
# achieve a continuous azimuthal integration range
|
|
559
|
+
# If the discontinuity is crossed, artificially rotate the
|
|
560
|
+
# detectors to achieve a continuous azimuthal integration range
|
|
435
561
|
if chi_min < chi_disc and chi_max > chi_disc:
|
|
436
562
|
chi_offset = chi_max - chi_disc
|
|
437
563
|
else:
|
|
438
564
|
chi_offset = 0
|
|
439
|
-
return
|
|
565
|
+
return chi_min-chi_offset, chi_max-chi_offset, chi_offset, chi_disc
|
|
566
|
+
|
|
567
|
+
|
|
440
568
|
@cache
|
|
441
569
|
def get_azimuthal_integrators(poni_files:tuple, chi_offset=0):
|
|
442
|
-
"""
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
:param poni_files: Tuple of strings, each string being a path to a
|
|
570
|
+
"""Return a list of `AzimuthalIntegrator` objects generated from
|
|
571
|
+
PONI files.
|
|
572
|
+
|
|
573
|
+
:param poni_files: Tuple of strings, each string being a path to a
|
|
574
|
+
PONI file.
|
|
446
575
|
:type poni_files: tuple
|
|
447
|
-
:param chi_offset: The angle in degrees by which the
|
|
576
|
+
:param chi_offset: The angle in degrees by which the
|
|
577
|
+
`AzimuthalIntegrator` objects will be rotated, defaults to 0.
|
|
448
578
|
:type chi_offset: float, optional
|
|
449
579
|
:return: List of `AzimuthalIntegrator` objects
|
|
450
580
|
:rtype: list[pyFAI.azimuthalIntegrator.AzimuthalIntegrator]
|
|
@@ -454,62 +584,75 @@ def get_azimuthal_integrators(poni_files:tuple, chi_offset=0):
|
|
|
454
584
|
ai = copy.deepcopy(azimuthal_integrator(poni_file))
|
|
455
585
|
ai.rot3 += chi_offset * np.pi/180
|
|
456
586
|
ais.append(ai)
|
|
457
|
-
return
|
|
587
|
+
return ais
|
|
588
|
+
|
|
589
|
+
|
|
458
590
|
@cache
|
|
459
|
-
def get_multi_geometry_integrator(poni_files:tuple, radial_unit:str,
|
|
460
|
-
|
|
461
|
-
|
|
591
|
+
def get_multi_geometry_integrator(poni_files:tuple, radial_unit:str,
|
|
592
|
+
radial_range:tuple, azimuthal_range:tuple):
|
|
593
|
+
"""Return a `MultiGeometry` instance that can be used for
|
|
594
|
+
azimuthal or cake integration.
|
|
462
595
|
|
|
463
|
-
:param poni_files: Tuple of PONI files that describe the detectors
|
|
464
|
-
integrated.
|
|
596
|
+
:param poni_files: Tuple of PONI files that describe the detectors
|
|
597
|
+
to be integrated.
|
|
465
598
|
:type poni_files: tuple
|
|
466
599
|
:param radial_unit: Unit to use for radial integration range.
|
|
467
600
|
:type radial_unit: str
|
|
468
601
|
:param radial_range: Tuple describing the range for radial integration.
|
|
469
602
|
:type radial_range: tuple[float,float]
|
|
470
|
-
:param azimuthal_range:Tuple describing the range for azimuthal
|
|
471
|
-
:type azimuthal_range: tuple[float,float]
|
|
472
|
-
:return: `MultiGeometry` instance that can be used for azimuthal or cake
|
|
603
|
+
:param azimuthal_range:Tuple describing the range for azimuthal
|
|
473
604
|
integration.
|
|
605
|
+
:type azimuthal_range: tuple[float,float]
|
|
606
|
+
:return: `MultiGeometry` instance that can be used for azimuthal
|
|
607
|
+
or cake integration.
|
|
474
608
|
:rtype: pyFAI.multi_geometry.MultiGeometry
|
|
475
609
|
"""
|
|
476
|
-
chi_min, chi_max, chi_offset, chi_disc =
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
610
|
+
chi_min, chi_max, chi_offset, chi_disc = \
|
|
611
|
+
get_azimuthal_adjustments(*azimuthal_range)
|
|
612
|
+
ais = copy.deepcopy(get_azimuthal_integrators(poni_files,
|
|
613
|
+
chi_offset=chi_offset))
|
|
614
|
+
multi_geometry = MultiGeometry(
|
|
615
|
+
ais,
|
|
616
|
+
unit=radial_unit,
|
|
617
|
+
radial_range=radial_range,
|
|
618
|
+
azimuth_range=(chi_min, chi_max),
|
|
619
|
+
wavelength=sum([ai.wavelength for ai in ais])/len(ais),
|
|
620
|
+
chi_disc=chi_disc)
|
|
621
|
+
return multi_geometry
|
|
622
|
+
|
|
623
|
+
|
|
485
624
|
@cache
|
|
486
|
-
def get_integrated_data_coordinates(azimuthal_range:tuple
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
625
|
+
def get_integrated_data_coordinates(azimuthal_range:tuple = None,
|
|
626
|
+
azimuthal_npt:int = None,
|
|
627
|
+
radial_range:tuple = None,
|
|
628
|
+
radial_npt:int = None):
|
|
629
|
+
"""Return a dictionary of coordinate arrays for the specified
|
|
630
|
+
radial and/or azimuthal integration ranges.
|
|
631
|
+
|
|
632
|
+
:param azimuthal_range: Tuple specifying the range of azimuthal
|
|
633
|
+
angles over which to generate coordinates, in the format (min,
|
|
634
|
+
max), defaults to None.
|
|
494
635
|
:type azimuthal_range: tuple[float,float], optional
|
|
495
|
-
:param azimuthal_npt: Number of azimuthal coordinate points to
|
|
496
|
-
defaults to None.
|
|
636
|
+
:param azimuthal_npt: Number of azimuthal coordinate points to
|
|
637
|
+
generate, defaults to None.
|
|
497
638
|
:type azimuthal_npt: int, optional
|
|
498
|
-
:param radial_range: Tuple specifying the range of radial
|
|
499
|
-
which to generate coordinates, in the format
|
|
500
|
-
None.
|
|
639
|
+
:param radial_range: Tuple specifying the range of radial
|
|
640
|
+
distances over which to generate coordinates, in the format
|
|
641
|
+
(min, max), defaults to None.
|
|
501
642
|
:type radial_range: tuple[float,float], optional
|
|
502
|
-
:param radial_npt: Number of radial coordinate points to generate,
|
|
503
|
-
to None.
|
|
643
|
+
:param radial_npt: Number of radial coordinate points to generate,
|
|
644
|
+
defaults to None.
|
|
504
645
|
:type radial_npt: int, optional
|
|
505
|
-
:return: A dictionary with either one or two keys: 'azimuthal'
|
|
506
|
-
'radial', each of which points to a 1-D `numpy` array
|
|
507
|
-
values.
|
|
646
|
+
:return: A dictionary with either one or two keys: 'azimuthal'
|
|
647
|
+
and/or 'radial', each of which points to a 1-D `numpy` array
|
|
648
|
+
of coordinate values.
|
|
508
649
|
:rtype: dict[str,np.ndarray]
|
|
509
650
|
"""
|
|
510
651
|
integrated_data_coordinates = {}
|
|
511
652
|
if azimuthal_range is not None and azimuthal_npt is not None:
|
|
512
|
-
integrated_data_coordinates['azimuthal'] = np.linspace(
|
|
653
|
+
integrated_data_coordinates['azimuthal'] = np.linspace(
|
|
654
|
+
*azimuthal_range, azimuthal_npt)
|
|
513
655
|
if radial_range is not None and radial_npt is not None:
|
|
514
|
-
integrated_data_coordinates['radial'] = np.linspace(
|
|
515
|
-
|
|
656
|
+
integrated_data_coordinates['radial'] = np.linspace(
|
|
657
|
+
*radial_range, radial_npt)
|
|
658
|
+
return integrated_data_coordinates
|