diffpy.utils 3.6.0rc4__py3-none-any.whl → 3.6.1__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.
- diffpy/utils/__init__.py +4 -2
- diffpy/utils/diffraction_objects.py +143 -65
- diffpy/utils/parsers/custom_exceptions.py +3 -1
- diffpy/utils/parsers/loaddata.py +61 -32
- diffpy/utils/parsers/serialization.py +29 -14
- diffpy/utils/resampler.py +28 -21
- diffpy/utils/tools.py +131 -70
- diffpy/utils/transforms.py +21 -12
- diffpy/utils/validators.py +3 -2
- diffpy/utils/version.py +4 -2
- diffpy/utils/wx/gridutils.py +9 -3
- {diffpy.utils-3.6.0rc4.dist-info → diffpy_utils-3.6.1.dist-info}/METADATA +24 -16
- diffpy_utils-3.6.1.dist-info/RECORD +21 -0
- {diffpy.utils-3.6.0rc4.dist-info → diffpy_utils-3.6.1.dist-info}/WHEEL +1 -1
- diffpy.utils-3.6.0rc4.dist-info/RECORD +0 -21
- {diffpy.utils-3.6.0rc4.dist-info → diffpy_utils-3.6.1.dist-info/licenses}/AUTHORS.rst +0 -0
- {diffpy.utils-3.6.0rc4.dist-info → diffpy_utils-3.6.1.dist-info/licenses}/LICENSE.rst +0 -0
- {diffpy.utils-3.6.0rc4.dist-info → diffpy_utils-3.6.1.dist-info/licenses}/LICENSE_DANSE.txt +0 -0
- {diffpy.utils-3.6.0rc4.dist-info → diffpy_utils-3.6.1.dist-info}/top_level.txt +0 -0
diffpy/utils/__init__.py
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env python
|
|
2
2
|
##############################################################################
|
|
3
3
|
#
|
|
4
|
-
# (c)
|
|
4
|
+
# (c) 2025 The Trustees of Columbia University in the City of New York.
|
|
5
5
|
# All rights reserved.
|
|
6
6
|
#
|
|
7
|
-
# File coded by: Billinge Group members
|
|
7
|
+
# File coded by: Simon Billinge, Billinge Group members.
|
|
8
8
|
#
|
|
9
9
|
# See GitHub contributions for a more detailed list of contributors.
|
|
10
10
|
# https://github.com/diffpy/diffpy.utils/graphs/contributors
|
|
@@ -19,3 +19,5 @@ from diffpy.utils.version import __version__
|
|
|
19
19
|
|
|
20
20
|
# silence the pyflakes syntax checker
|
|
21
21
|
assert __version__ or True
|
|
22
|
+
|
|
23
|
+
# End of file
|
|
@@ -6,24 +6,42 @@ from copy import deepcopy
|
|
|
6
6
|
import numpy as np
|
|
7
7
|
|
|
8
8
|
from diffpy.utils.tools import get_package_info
|
|
9
|
-
from diffpy.utils.transforms import
|
|
9
|
+
from diffpy.utils.transforms import (
|
|
10
|
+
d_to_q,
|
|
11
|
+
d_to_tth,
|
|
12
|
+
q_to_d,
|
|
13
|
+
q_to_tth,
|
|
14
|
+
tth_to_d,
|
|
15
|
+
tth_to_q,
|
|
16
|
+
)
|
|
10
17
|
|
|
11
18
|
QQUANTITIES = ["q"]
|
|
12
19
|
ANGLEQUANTITIES = ["angle", "tth", "twotheta", "2theta"]
|
|
13
20
|
DQUANTITIES = ["d", "dspace"]
|
|
14
21
|
XQUANTITIES = ANGLEQUANTITIES + DQUANTITIES + QQUANTITIES
|
|
15
|
-
XUNITS = [
|
|
22
|
+
XUNITS = [
|
|
23
|
+
"degrees",
|
|
24
|
+
"radians",
|
|
25
|
+
"rad",
|
|
26
|
+
"deg",
|
|
27
|
+
"inv_angs",
|
|
28
|
+
"inv_nm",
|
|
29
|
+
"nm-1",
|
|
30
|
+
"A-1",
|
|
31
|
+
]
|
|
16
32
|
|
|
17
33
|
x_values_not_equal_emsg = (
|
|
18
|
-
"The two objects have different values in x arrays
|
|
19
|
-
"
|
|
20
|
-
"the
|
|
34
|
+
"The two objects have different values in x arrays "
|
|
35
|
+
"(my_do.all_arrays[:, [1, 2, 3]]). "
|
|
36
|
+
"Please ensure the x values of the two objects are identical by "
|
|
37
|
+
"re-instantiating the DiffractionObject with the correct x value inputs."
|
|
21
38
|
)
|
|
22
39
|
|
|
23
40
|
invalid_add_type_emsg = (
|
|
24
|
-
"You may only add a DiffractionObject with another DiffractionObject or
|
|
25
|
-
"
|
|
26
|
-
"
|
|
41
|
+
"You may only add a DiffractionObject with another DiffractionObject or "
|
|
42
|
+
"a scalar value. "
|
|
43
|
+
"Please rerun by adding another DiffractionObject instance or a "
|
|
44
|
+
"scalar value. e.g., my_do_1 + my_do_2 or my_do + 10 or 10 + my_do"
|
|
27
45
|
)
|
|
28
46
|
|
|
29
47
|
|
|
@@ -54,11 +72,14 @@ class DiffractionObject:
|
|
|
54
72
|
Attributes
|
|
55
73
|
----------
|
|
56
74
|
scat_quantity : str
|
|
57
|
-
The type of scattering experiment (e.g., "x-ray", "neutron"). Default
|
|
75
|
+
The type of scattering experiment (e.g., "x-ray", "neutron"). Default
|
|
76
|
+
is an empty string "".
|
|
58
77
|
wavelength : float
|
|
59
|
-
The wavelength of the incoming beam, specified in angstroms (Å).
|
|
78
|
+
The wavelength of the incoming beam, specified in angstroms (Å).
|
|
79
|
+
Default is none.
|
|
60
80
|
name: str
|
|
61
|
-
The name or label for the scattering data. Default is an empty string
|
|
81
|
+
The name or label for the scattering data. Default is an empty string
|
|
82
|
+
"".
|
|
62
83
|
qmin : float
|
|
63
84
|
The minimum q value.
|
|
64
85
|
qmax : float
|
|
@@ -92,7 +113,8 @@ class DiffractionObject:
|
|
|
92
113
|
yarray : ndarray
|
|
93
114
|
The dependent variable array corresponding to intensity values.
|
|
94
115
|
xtype : str
|
|
95
|
-
The type of the independent variable in `xarray`. Must be one of
|
|
116
|
+
The type of the independent variable in `xarray`. Must be one of
|
|
117
|
+
{*XQUANTITIES}.
|
|
96
118
|
wavelength : float, optional, default is None.
|
|
97
119
|
The wavelength of the incoming beam, specified in angstroms (Å)
|
|
98
120
|
scat_quantity : str, optional, default is an empty string "".
|
|
@@ -108,7 +130,7 @@ class DiffractionObject:
|
|
|
108
130
|
>>> import numpy as np
|
|
109
131
|
>>> from diffpy.utils.diffraction_objects import DiffractionObject
|
|
110
132
|
...
|
|
111
|
-
>>> x = np.array([0.12, 0.24, 0.31, 0.4]) # independent variable (e.g., q)
|
|
133
|
+
>>> x = np.array([0.12, 0.24, 0.31, 0.4]) # independent variable (e.g., q) # noqa: E501
|
|
112
134
|
>>> y = np.array([10, 20, 40, 60]) # intensity values
|
|
113
135
|
>>> metadata = {
|
|
114
136
|
... "sample": "rock salt from the beach",
|
|
@@ -129,9 +151,13 @@ class DiffractionObject:
|
|
|
129
151
|
"""
|
|
130
152
|
|
|
131
153
|
self._uuid = uuid.uuid4()
|
|
132
|
-
self._input_data(
|
|
154
|
+
self._input_data(
|
|
155
|
+
xarray, yarray, xtype, wavelength, scat_quantity, name, metadata
|
|
156
|
+
)
|
|
133
157
|
|
|
134
|
-
def _input_data(
|
|
158
|
+
def _input_data(
|
|
159
|
+
self, xarray, yarray, xtype, wavelength, scat_quantity, name, metadata
|
|
160
|
+
):
|
|
135
161
|
if xtype not in XQUANTITIES:
|
|
136
162
|
raise ValueError(_xtype_wmsg(xtype))
|
|
137
163
|
if len(xarray) != len(yarray):
|
|
@@ -152,8 +178,12 @@ class DiffractionObject:
|
|
|
152
178
|
def __eq__(self, other):
|
|
153
179
|
if not isinstance(other, DiffractionObject):
|
|
154
180
|
return NotImplemented
|
|
155
|
-
self_attributes = [
|
|
156
|
-
|
|
181
|
+
self_attributes = [
|
|
182
|
+
key for key in self.__dict__ if not key.startswith("_")
|
|
183
|
+
]
|
|
184
|
+
other_attributes = [
|
|
185
|
+
key for key in other.__dict__ if not key.startswith("_")
|
|
186
|
+
]
|
|
157
187
|
if not sorted(self_attributes) == sorted(other_attributes):
|
|
158
188
|
return False
|
|
159
189
|
for key in self_attributes:
|
|
@@ -167,8 +197,13 @@ class DiffractionObject:
|
|
|
167
197
|
or not np.isclose(value, other_value, rtol=1e-5)
|
|
168
198
|
):
|
|
169
199
|
return False
|
|
170
|
-
elif isinstance(value, list) and all(
|
|
171
|
-
|
|
200
|
+
elif isinstance(value, list) and all(
|
|
201
|
+
isinstance(i, np.ndarray) for i in value
|
|
202
|
+
):
|
|
203
|
+
if not all(
|
|
204
|
+
np.allclose(i, j, rtol=1e-5)
|
|
205
|
+
for i, j in zip(value, other_value)
|
|
206
|
+
):
|
|
172
207
|
return False
|
|
173
208
|
else:
|
|
174
209
|
if value != other_value:
|
|
@@ -182,23 +217,29 @@ class DiffractionObject:
|
|
|
182
217
|
Parameters
|
|
183
218
|
----------
|
|
184
219
|
other : DiffractionObject, int, or float
|
|
185
|
-
The item to be added. If `other` is a scalar value, this value
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
220
|
+
The item to be added. If `other` is a scalar value, this value
|
|
221
|
+
will be added to each element of the yarray of this
|
|
222
|
+
DiffractionObject instance. If `other` is another DiffractionObject
|
|
223
|
+
, the yarrays of the two DiffractionObjects will be combined
|
|
224
|
+
element -wise. The result is a new DiffractionObject instance,
|
|
225
|
+
representing the addition and using the xarray from the left-hand
|
|
226
|
+
side DiffractionObject.
|
|
189
227
|
|
|
190
228
|
Returns
|
|
191
229
|
-------
|
|
192
230
|
DiffractionObject
|
|
193
|
-
The new DiffractionObject instance with modified yarray values.
|
|
194
|
-
original with the additions
|
|
231
|
+
The new DiffractionObject instance with modified yarray values.
|
|
232
|
+
This instance is a deep copy of the original with the additions
|
|
233
|
+
applied.
|
|
195
234
|
|
|
196
235
|
Raises
|
|
197
236
|
------
|
|
198
237
|
ValueError
|
|
199
|
-
Raised when the xarrays of two DiffractionObject instances are
|
|
238
|
+
Raised when the xarrays of two DiffractionObject instances are
|
|
239
|
+
not equal.
|
|
200
240
|
TypeError
|
|
201
|
-
Raised when `other` is not an instance of DiffractionObject, int,
|
|
241
|
+
Raised when `other` is not an instance of DiffractionObject, int,
|
|
242
|
+
or float.
|
|
202
243
|
|
|
203
244
|
Examples
|
|
204
245
|
--------
|
|
@@ -224,12 +265,14 @@ class DiffractionObject:
|
|
|
224
265
|
"""Subtract scalar value or another DiffractionObject to the yarray of
|
|
225
266
|
the DiffractionObject.
|
|
226
267
|
|
|
227
|
-
This method behaves similarly to the `__add__` method, but performs
|
|
228
|
-
For details on parameters, returns
|
|
268
|
+
This method behaves similarly to the `__add__` method, but performs
|
|
269
|
+
subtraction instead of addition. For details on parameters, returns
|
|
270
|
+
, and exceptions, refer to the documentation for `__add__`.
|
|
229
271
|
|
|
230
272
|
Examples
|
|
231
273
|
--------
|
|
232
|
-
Subtract a scalar value from the yarray of a DiffractionObject
|
|
274
|
+
Subtract a scalar value from the yarray of a DiffractionObject
|
|
275
|
+
instance:
|
|
233
276
|
>>> new_do = my_do - 10.1
|
|
234
277
|
|
|
235
278
|
Subtract the yarrays of two DiffractionObject instances:
|
|
@@ -250,12 +293,14 @@ class DiffractionObject:
|
|
|
250
293
|
"""Multiply a scalar value or another DiffractionObject with the yarray
|
|
251
294
|
of this DiffractionObject.
|
|
252
295
|
|
|
253
|
-
This method behaves similarly to the `__add__` method, but performs
|
|
254
|
-
For details on parameters,
|
|
296
|
+
This method behaves similarly to the `__add__` method, but performs
|
|
297
|
+
multiplication instead of addition. For details on parameters,
|
|
298
|
+
returns, and exceptions, refer to the documentation for `__add__`.
|
|
255
299
|
|
|
256
300
|
Examples
|
|
257
301
|
--------
|
|
258
|
-
Multiply a scalar value with the yarray of a DiffractionObject
|
|
302
|
+
Multiply a scalar value with the yarray of a DiffractionObject
|
|
303
|
+
instance:
|
|
259
304
|
>>> new_do = my_do * 3.5
|
|
260
305
|
|
|
261
306
|
Multiply the yarrays of two DiffractionObject instances:
|
|
@@ -276,8 +321,9 @@ class DiffractionObject:
|
|
|
276
321
|
"""Divide the yarray of this DiffractionObject by a scalar value or
|
|
277
322
|
another DiffractionObject.
|
|
278
323
|
|
|
279
|
-
This method behaves similarly to the `__add__` method, but performs
|
|
280
|
-
For details on parameters, returns,
|
|
324
|
+
This method behaves similarly to the `__add__` method, but performs
|
|
325
|
+
division instead of addition. For details on parameters, returns,
|
|
326
|
+
and exceptions, refer to the documentation for `__add__`.
|
|
281
327
|
|
|
282
328
|
Examples
|
|
283
329
|
--------
|
|
@@ -303,7 +349,9 @@ class DiffractionObject:
|
|
|
303
349
|
if isinstance(other, DiffractionObject):
|
|
304
350
|
if self.all_arrays.shape != other.all_arrays.shape:
|
|
305
351
|
raise ValueError(x_values_not_equal_emsg)
|
|
306
|
-
if not np.allclose(
|
|
352
|
+
if not np.allclose(
|
|
353
|
+
self.all_arrays[:, [1, 2, 3]], other.all_arrays[:, [1, 2, 3]]
|
|
354
|
+
):
|
|
307
355
|
raise ValueError(x_values_not_equal_emsg)
|
|
308
356
|
|
|
309
357
|
@property
|
|
@@ -313,8 +361,8 @@ class DiffractionObject:
|
|
|
313
361
|
Returns
|
|
314
362
|
-------
|
|
315
363
|
ndarray
|
|
316
|
-
The shape (len(data), 4) 2D array with columns containing the `
|
|
317
|
-
and the `xarray` values in q, tth, and d.
|
|
364
|
+
The shape (len(data), 4) 2D array with columns containing the `
|
|
365
|
+
yarray` (intensity) and the `xarray` values in q, tth, and d.
|
|
318
366
|
|
|
319
367
|
Examples
|
|
320
368
|
--------
|
|
@@ -361,27 +409,35 @@ class DiffractionObject:
|
|
|
361
409
|
def uuid(self, _):
|
|
362
410
|
raise AttributeError(_setter_wmsg("uuid"))
|
|
363
411
|
|
|
364
|
-
def get_array_index(self,
|
|
365
|
-
"""Return the index of the closest value in the array associated with
|
|
412
|
+
def get_array_index(self, xvalue, xtype=None):
|
|
413
|
+
f"""Return the index of the closest value in the array associated with
|
|
366
414
|
the specified xtype and the value provided.
|
|
367
415
|
|
|
368
416
|
Parameters
|
|
369
417
|
----------
|
|
370
|
-
xtype : str
|
|
371
|
-
The type of the independent variable in `xarray`. Must be one of {*XQUANTITIES}.
|
|
372
418
|
xvalue : float
|
|
373
419
|
The value of the xtype to find the closest index for.
|
|
420
|
+
xtype : str, optional
|
|
421
|
+
The type of the independent variable in `xarray`. Must be one
|
|
422
|
+
of {*XQUANTITIES, }. Default is {self._input_xtype}
|
|
374
423
|
|
|
375
424
|
Returns
|
|
376
425
|
-------
|
|
377
426
|
index : int
|
|
378
|
-
The index of the closest value in the array associated with the
|
|
427
|
+
The index of the closest value in the array associated with the
|
|
428
|
+
specified xtype and the value provided.
|
|
379
429
|
"""
|
|
380
|
-
|
|
381
|
-
|
|
430
|
+
if xtype is None:
|
|
431
|
+
xtype = self._input_xtype
|
|
432
|
+
else:
|
|
433
|
+
if xtype not in XQUANTITIES:
|
|
434
|
+
raise ValueError(_xtype_wmsg(xtype))
|
|
382
435
|
xarray = self.on_xtype(xtype)[0]
|
|
383
436
|
if len(xarray) == 0:
|
|
384
|
-
raise ValueError(
|
|
437
|
+
raise ValueError(
|
|
438
|
+
f"The '{xtype}' array is empty. "
|
|
439
|
+
"Please ensure it is initialized."
|
|
440
|
+
)
|
|
385
441
|
index = (np.abs(xarray - xvalue)).argmin()
|
|
386
442
|
return index
|
|
387
443
|
|
|
@@ -447,14 +503,19 @@ class DiffractionObject:
|
|
|
447
503
|
"""
|
|
448
504
|
return [self.all_arrays[:, 3], self.all_arrays[:, 0]]
|
|
449
505
|
|
|
450
|
-
def scale_to(
|
|
506
|
+
def scale_to(
|
|
507
|
+
self, target_diff_object, q=None, tth=None, d=None, offset=None
|
|
508
|
+
):
|
|
451
509
|
"""Return a new diffraction object which is the current object but
|
|
452
510
|
rescaled in y to the target.
|
|
453
511
|
|
|
454
|
-
By default, if `q`, `tth`, or `d` are not provided, scaling is
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
512
|
+
By default, if `q`, `tth`, or `d` are not provided, scaling is
|
|
513
|
+
based on the max intensity from each object. Otherwise, y-value in
|
|
514
|
+
the target at the closest specified x-value will be used as the
|
|
515
|
+
factor to scale to. The entire array is scaled by this factor so
|
|
516
|
+
that one object places on top of the other at that point. If
|
|
517
|
+
multiple values of `q`, `tth`, or `d` are provided, an error will
|
|
518
|
+
be raised.
|
|
458
519
|
|
|
459
520
|
Parameters
|
|
460
521
|
----------
|
|
@@ -462,8 +523,9 @@ class DiffractionObject:
|
|
|
462
523
|
The diffraction object you want to scale the current one onto.
|
|
463
524
|
|
|
464
525
|
q, tth, d : float, optional, default is None
|
|
465
|
-
The value of the x-array where you want the curves to line up
|
|
466
|
-
Specify a value on one of the allowed grids, q, tth,
|
|
526
|
+
The value of the x-array where you want the curves to line up
|
|
527
|
+
vertically. Specify a value on one of the allowed grids, q, tth,
|
|
528
|
+
or d), e.g., q=10.
|
|
467
529
|
|
|
468
530
|
offset : float, optional, default is None
|
|
469
531
|
The offset to add to the scaled y-values.
|
|
@@ -486,7 +548,10 @@ class DiffractionObject:
|
|
|
486
548
|
if count == 0:
|
|
487
549
|
q_target_max = max(target_diff_object.on_q()[1])
|
|
488
550
|
q_self_max = max(self.on_q()[1])
|
|
489
|
-
scaled_do._all_arrays[:, 0] =
|
|
551
|
+
scaled_do._all_arrays[:, 0] = (
|
|
552
|
+
scaled_do._all_arrays[:, 0] * q_target_max / q_self_max
|
|
553
|
+
+ offset
|
|
554
|
+
)
|
|
490
555
|
return scaled_do
|
|
491
556
|
|
|
492
557
|
xtype = "q" if q is not None else "tth" if tth is not None else "d"
|
|
@@ -497,7 +562,9 @@ class DiffractionObject:
|
|
|
497
562
|
|
|
498
563
|
xindex_data = (np.abs(data[0] - xvalue)).argmin()
|
|
499
564
|
xindex_target = (np.abs(target[0] - xvalue)).argmin()
|
|
500
|
-
scaled_do._all_arrays[:, 0] =
|
|
565
|
+
scaled_do._all_arrays[:, 0] = (
|
|
566
|
+
data[1] * target[1][xindex_target] / data[1][xindex_data] + offset
|
|
567
|
+
)
|
|
501
568
|
return scaled_do
|
|
502
569
|
|
|
503
570
|
def on_xtype(self, xtype):
|
|
@@ -506,7 +573,8 @@ class DiffractionObject:
|
|
|
506
573
|
Parameters
|
|
507
574
|
----------
|
|
508
575
|
xtype : str
|
|
509
|
-
The type of quantity for the independent variable chosen from
|
|
576
|
+
The type of quantity for the independent variable chosen from
|
|
577
|
+
{*XQUANTITIES, }
|
|
510
578
|
|
|
511
579
|
Raises
|
|
512
580
|
------
|
|
@@ -516,7 +584,8 @@ class DiffractionObject:
|
|
|
516
584
|
Returns
|
|
517
585
|
-------
|
|
518
586
|
(xarray, yarray) : tuple of ndarray
|
|
519
|
-
The tuple containing two 1D numpy arrays with x and y data for
|
|
587
|
+
The tuple containing two 1D numpy arrays with x and y data for
|
|
588
|
+
the specified xtype.
|
|
520
589
|
"""
|
|
521
590
|
if xtype.lower() in ANGLEQUANTITIES:
|
|
522
591
|
return self.on_tth()
|
|
@@ -536,12 +605,13 @@ class DiffractionObject:
|
|
|
536
605
|
filepath : str
|
|
537
606
|
The filepath where the diffraction object will be dumped
|
|
538
607
|
xtype : str, optional, default is q
|
|
539
|
-
The type of quantity for the independent variable chosen from
|
|
608
|
+
The type of quantity for the independent variable chosen from
|
|
609
|
+
{*XQUANTITIES, }
|
|
540
610
|
|
|
541
611
|
Examples
|
|
542
612
|
--------
|
|
543
|
-
To save a diffraction object to a file named "diffraction_data.chi"
|
|
544
|
-
with the independent variable 'q':
|
|
613
|
+
To save a diffraction object to a file named "diffraction_data.chi"
|
|
614
|
+
in the current directory with the independent variable 'q':
|
|
545
615
|
|
|
546
616
|
>>> file = "diffraction_data.chi"
|
|
547
617
|
>>> do.dump(file, xtype="q")
|
|
@@ -551,7 +621,8 @@ class DiffractionObject:
|
|
|
551
621
|
>>> file = "./output/diffraction_data.chi"
|
|
552
622
|
>>> do.dump(file, xtype="q")
|
|
553
623
|
|
|
554
|
-
To save the diffraction data with a different independent variable,
|
|
624
|
+
To save the diffraction data with a different independent variable,
|
|
625
|
+
such as 'tth':
|
|
555
626
|
|
|
556
627
|
>>> file = "diffraction_data_tth.chi"
|
|
557
628
|
>>> do.dump(file, xtype="tth")
|
|
@@ -561,17 +632,23 @@ class DiffractionObject:
|
|
|
561
632
|
if xtype in QQUANTITIES:
|
|
562
633
|
data_to_save = np.column_stack((self.on_q()[0], self.on_q()[1]))
|
|
563
634
|
elif xtype in ANGLEQUANTITIES:
|
|
564
|
-
data_to_save = np.column_stack(
|
|
635
|
+
data_to_save = np.column_stack(
|
|
636
|
+
(self.on_tth()[0], self.on_tth()[1])
|
|
637
|
+
)
|
|
565
638
|
elif xtype in DQUANTITIES:
|
|
566
639
|
data_to_save = np.column_stack((self.on_d()[0], self.on_d()[1]))
|
|
567
640
|
else:
|
|
568
641
|
warnings.warn(_xtype_wmsg(xtype))
|
|
569
|
-
self.metadata.update(
|
|
642
|
+
self.metadata.update(
|
|
643
|
+
get_package_info("diffpy.utils", metadata=self.metadata)
|
|
644
|
+
)
|
|
570
645
|
self.metadata["creation_time"] = datetime.datetime.now()
|
|
571
646
|
|
|
572
647
|
with open(filepath, "w") as f:
|
|
573
648
|
f.write(
|
|
574
|
-
f"[DiffractionObject]\
|
|
649
|
+
f"[DiffractionObject]\n"
|
|
650
|
+
f"name = {self.name}\n"
|
|
651
|
+
f"wavelength = {self.wavelength}\n"
|
|
575
652
|
f"scat_quantity = {self.scat_quantity}\n"
|
|
576
653
|
)
|
|
577
654
|
for key, value in self.metadata.items():
|
|
@@ -585,6 +662,7 @@ class DiffractionObject:
|
|
|
585
662
|
Returns
|
|
586
663
|
-------
|
|
587
664
|
DiffractionObject
|
|
588
|
-
The new instance of DiffractionObject, which is a deep copy of
|
|
665
|
+
The new instance of DiffractionObject, which is a deep copy of
|
|
666
|
+
the current instance.
|
|
589
667
|
"""
|
|
590
668
|
return deepcopy(self)
|
|
@@ -51,5 +51,7 @@ class ImproperSizeError(Exception):
|
|
|
51
51
|
|
|
52
52
|
def __init__(self, bad_object, message=None):
|
|
53
53
|
if message is None:
|
|
54
|
-
self.message =
|
|
54
|
+
self.message = (
|
|
55
|
+
f"The size of {bad_object} is different than expected."
|
|
56
|
+
)
|
|
55
57
|
super().__init__(self.message)
|
diffpy/utils/parsers/loaddata.py
CHANGED
|
@@ -20,56 +20,67 @@ import numpy
|
|
|
20
20
|
from diffpy.utils import validators
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
def loadData(
|
|
23
|
+
def loadData(
|
|
24
|
+
filename, minrows=10, headers=False, hdel="=", hignore=None, **kwargs
|
|
25
|
+
):
|
|
24
26
|
"""Find and load data from a text file.
|
|
25
27
|
|
|
26
|
-
The data block is identified as the first matrix block of at least
|
|
27
|
-
|
|
28
|
+
The data block is identified as the first matrix block of at least
|
|
29
|
+
minrows rows and constant number of columns. This seems to work for most
|
|
30
|
+
of the datafiles including those generated by diffpy programs.
|
|
28
31
|
|
|
29
32
|
Parameters
|
|
30
33
|
----------
|
|
31
34
|
filename
|
|
32
35
|
Name of the file we want to load data from.
|
|
33
36
|
minrows: int
|
|
34
|
-
Minimum number of rows in the first data block. All rows must have
|
|
35
|
-
point values.
|
|
37
|
+
Minimum number of rows in the first data block. All rows must have
|
|
38
|
+
the same number of floating point values.
|
|
36
39
|
headers: bool
|
|
37
|
-
when False (default), the function returns a numpy array of the data
|
|
38
|
-
When True, the function instead returns a
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
when False (default), the function returns a numpy array of the data
|
|
41
|
+
in the data block. When True, the function instead returns a
|
|
42
|
+
dictionary of parameters and their corresponding values parsed from
|
|
43
|
+
header (information prior the data block). See hdel and hignore for
|
|
44
|
+
options to help with parsing header information.
|
|
41
45
|
hdel: str
|
|
42
|
-
(Only used when headers enabled.) Delimiter for parsing header
|
|
43
|
-
default
|
|
46
|
+
(Only used when headers enabled.) Delimiter for parsing header
|
|
47
|
+
information (default '='). e.g. using default hdel, the line '
|
|
48
|
+
parameter = p_value' is put into the dictionary as
|
|
49
|
+
{parameter: p_value}.
|
|
44
50
|
hignore: list
|
|
45
|
-
(Only used when headers enabled.) Ignore header rows beginning with
|
|
46
|
-
e.g. hignore=['# ', '['] causes the
|
|
51
|
+
(Only used when headers enabled.) Ignore header rows beginning with
|
|
52
|
+
any elements in hignore. e.g. hignore=['# ', '['] causes the
|
|
53
|
+
following lines to be skipped: '# qmax=10', '[defaults]'.
|
|
47
54
|
kwargs:
|
|
48
|
-
Keyword arguments that are passed to numpy.loadtxt including the
|
|
49
|
-
numpy.loadtxt for more details.) Only
|
|
55
|
+
Keyword arguments that are passed to numpy.loadtxt including the
|
|
56
|
+
following arguments below. (See numpy.loadtxt for more details.) Only
|
|
57
|
+
pass kwargs used by numpy.loadtxt.
|
|
50
58
|
|
|
51
59
|
Useful kwargs
|
|
52
60
|
=============
|
|
53
61
|
comments: str, sequence of str
|
|
54
|
-
The characters or list of characters used to indicate the start of a
|
|
55
|
-
Comment lines are ignored.
|
|
62
|
+
The characters or list of characters used to indicate the start of a
|
|
63
|
+
comment (default '#'). Comment lines are ignored.
|
|
56
64
|
delimiter: str
|
|
57
|
-
Delimiter for the data in the block (default use whitespace). For
|
|
58
|
-
set delimiter to ','.
|
|
65
|
+
Delimiter for the data in the block (default use whitespace). For
|
|
66
|
+
comma-separated data blocks, set delimiter to ','.
|
|
59
67
|
unpack: bool
|
|
60
|
-
Return data as a sequence of columns that allows tuple unpacking such
|
|
61
|
-
loadData(FILENAME, unpack=True). Note transposing the
|
|
62
|
-
effect.
|
|
68
|
+
Return data as a sequence of columns that allows tuple unpacking such
|
|
69
|
+
as x, y = loadData(FILENAME, unpack=True). Note transposing the
|
|
70
|
+
loaded array as loadData(FILENAME).T has the same effect.
|
|
63
71
|
usecols:
|
|
64
|
-
Zero-based index of columns to be loaded, by default use all detected
|
|
65
|
-
data blocks that do not have the usecols-
|
|
72
|
+
Zero-based index of columns to be loaded, by default use all detected
|
|
73
|
+
columns. The reading skips data blocks that do not have the usecols-
|
|
74
|
+
specified columns.
|
|
66
75
|
|
|
67
76
|
Returns
|
|
68
77
|
-------
|
|
69
78
|
data_block: ndarray
|
|
70
|
-
A numpy array containing the found data block. (This is not returned
|
|
79
|
+
A numpy array containing the found data block. (This is not returned
|
|
80
|
+
if headers is enabled.)
|
|
71
81
|
hdata: dict
|
|
72
|
-
If headers are enabled, return a dictionary of parameters read from
|
|
82
|
+
If headers are enabled, return a dictionary of parameters read from
|
|
83
|
+
the header.
|
|
73
84
|
"""
|
|
74
85
|
from numpy import array, loadtxt
|
|
75
86
|
|
|
@@ -105,7 +116,12 @@ def loadData(filename, minrows=10, headers=False, hdel="=", hignore=None, **kwar
|
|
|
105
116
|
|
|
106
117
|
# Check if file exists before trying to open
|
|
107
118
|
if not os.path.exists(filename):
|
|
108
|
-
raise IOError(
|
|
119
|
+
raise IOError(
|
|
120
|
+
(
|
|
121
|
+
f"File {filename} cannot be found. "
|
|
122
|
+
"Please rerun the program specifying a valid filename."
|
|
123
|
+
)
|
|
124
|
+
)
|
|
109
125
|
|
|
110
126
|
# make sure fid gets cleaned up
|
|
111
127
|
with open(filename, "rb") as fid:
|
|
@@ -134,7 +150,10 @@ def loadData(filename, minrows=10, headers=False, hdel="=", hignore=None, **kwar
|
|
|
134
150
|
if hignore is not None:
|
|
135
151
|
for tag in hignore:
|
|
136
152
|
taglen = len(tag)
|
|
137
|
-
if
|
|
153
|
+
if (
|
|
154
|
+
len(hpair[0]) >= taglen
|
|
155
|
+
and hpair[0][:taglen] == tag
|
|
156
|
+
):
|
|
138
157
|
flag = False
|
|
139
158
|
# add header data
|
|
140
159
|
if flag:
|
|
@@ -187,7 +206,8 @@ class TextDataLoader(object):
|
|
|
187
206
|
minrows: int
|
|
188
207
|
Minimum number of rows in the first data block. (Default 10.)
|
|
189
208
|
usecols: tuple
|
|
190
|
-
Which columns in our dataset to use. Ignores all other columns. If
|
|
209
|
+
Which columns in our dataset to use. Ignores all other columns. If
|
|
210
|
+
None (default), use all columns.
|
|
191
211
|
skiprows
|
|
192
212
|
Rows in dataset to skip. (Currently not functional.)
|
|
193
213
|
"""
|
|
@@ -235,7 +255,8 @@ class TextDataLoader(object):
|
|
|
235
255
|
File details include:
|
|
236
256
|
* File name.
|
|
237
257
|
* All data blocks findable by loadData.
|
|
238
|
-
* Headers (if present) for each data block. (Generally the headers
|
|
258
|
+
* Headers (if present) for each data block. (Generally the headers
|
|
259
|
+
contain column name information).
|
|
239
260
|
"""
|
|
240
261
|
self._reset()
|
|
241
262
|
# try to read lines from fp first
|
|
@@ -258,7 +279,13 @@ class TextDataLoader(object):
|
|
|
258
279
|
# nf - number of words, ok - has data
|
|
259
280
|
self._linerecs = numpy.recarray(
|
|
260
281
|
(nlines,),
|
|
261
|
-
dtype=[
|
|
282
|
+
dtype=[
|
|
283
|
+
("idx", int),
|
|
284
|
+
("nw0", int),
|
|
285
|
+
("nw1", int),
|
|
286
|
+
("nf", int),
|
|
287
|
+
("ok", bool),
|
|
288
|
+
],
|
|
262
289
|
)
|
|
263
290
|
lr = self._linerecs
|
|
264
291
|
lr.idx = numpy.arange(nlines)
|
|
@@ -319,7 +346,9 @@ class TextDataLoader(object):
|
|
|
319
346
|
if self.usecols is None:
|
|
320
347
|
data = numpy.reshape(lw.value[bb1.nw0 : ee1.nw1], (-1, bb1.nf))
|
|
321
348
|
else:
|
|
322
|
-
tdata = numpy.empty(
|
|
349
|
+
tdata = numpy.empty(
|
|
350
|
+
(len(self.usecols), dend - dbeg), dtype=float
|
|
351
|
+
)
|
|
323
352
|
for j, trow in zip(self.usecols, tdata):
|
|
324
353
|
j %= bb1.nf
|
|
325
354
|
trow[:] = lw.value[bb1.nw0 + j : ee1.nw1 : bb1.nf]
|