diffpy.utils 3.6.0rc4__py3-none-any.whl → 3.6.1rc0__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 +135 -60
- 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.1rc0.dist-info}/METADATA +23 -15
- diffpy_utils-3.6.1rc0.dist-info/RECORD +21 -0
- {diffpy.utils-3.6.0rc4.dist-info → diffpy_utils-3.6.1rc0.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.1rc0.dist-info/licenses}/AUTHORS.rst +0 -0
- {diffpy.utils-3.6.0rc4.dist-info → diffpy_utils-3.6.1rc0.dist-info/licenses}/LICENSE.rst +0 -0
- {diffpy.utils-3.6.0rc4.dist-info → diffpy_utils-3.6.1rc0.dist-info/licenses}/LICENSE_DANSE.txt +0 -0
- {diffpy.utils-3.6.0rc4.dist-info → diffpy_utils-3.6.1rc0.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
|
--------
|
|
@@ -368,20 +416,25 @@ class DiffractionObject:
|
|
|
368
416
|
Parameters
|
|
369
417
|
----------
|
|
370
418
|
xtype : str
|
|
371
|
-
The type of the independent variable in `xarray`. Must be one
|
|
419
|
+
The type of the independent variable in `xarray`. Must be one
|
|
420
|
+
of {*XQUANTITIES}.
|
|
372
421
|
xvalue : float
|
|
373
422
|
The value of the xtype to find the closest index for.
|
|
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
430
|
|
|
381
431
|
xtype = self._input_xtype
|
|
382
432
|
xarray = self.on_xtype(xtype)[0]
|
|
383
433
|
if len(xarray) == 0:
|
|
384
|
-
raise ValueError(
|
|
434
|
+
raise ValueError(
|
|
435
|
+
f"The '{xtype}' array is empty. "
|
|
436
|
+
"Please ensure it is initialized."
|
|
437
|
+
)
|
|
385
438
|
index = (np.abs(xarray - xvalue)).argmin()
|
|
386
439
|
return index
|
|
387
440
|
|
|
@@ -447,14 +500,19 @@ class DiffractionObject:
|
|
|
447
500
|
"""
|
|
448
501
|
return [self.all_arrays[:, 3], self.all_arrays[:, 0]]
|
|
449
502
|
|
|
450
|
-
def scale_to(
|
|
503
|
+
def scale_to(
|
|
504
|
+
self, target_diff_object, q=None, tth=None, d=None, offset=None
|
|
505
|
+
):
|
|
451
506
|
"""Return a new diffraction object which is the current object but
|
|
452
507
|
rescaled in y to the target.
|
|
453
508
|
|
|
454
|
-
By default, if `q`, `tth`, or `d` are not provided, scaling is
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
509
|
+
By default, if `q`, `tth`, or `d` are not provided, scaling is
|
|
510
|
+
based on the max intensity from each object. Otherwise, y-value in
|
|
511
|
+
the target at the closest specified x-value will be used as the
|
|
512
|
+
factor to scale to. The entire array is scaled by this factor so
|
|
513
|
+
that one object places on top of the other at that point. If
|
|
514
|
+
multiple values of `q`, `tth`, or `d` are provided, an error will
|
|
515
|
+
be raised.
|
|
458
516
|
|
|
459
517
|
Parameters
|
|
460
518
|
----------
|
|
@@ -462,8 +520,9 @@ class DiffractionObject:
|
|
|
462
520
|
The diffraction object you want to scale the current one onto.
|
|
463
521
|
|
|
464
522
|
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,
|
|
523
|
+
The value of the x-array where you want the curves to line up
|
|
524
|
+
vertically. Specify a value on one of the allowed grids, q, tth,
|
|
525
|
+
or d), e.g., q=10.
|
|
467
526
|
|
|
468
527
|
offset : float, optional, default is None
|
|
469
528
|
The offset to add to the scaled y-values.
|
|
@@ -486,7 +545,10 @@ class DiffractionObject:
|
|
|
486
545
|
if count == 0:
|
|
487
546
|
q_target_max = max(target_diff_object.on_q()[1])
|
|
488
547
|
q_self_max = max(self.on_q()[1])
|
|
489
|
-
scaled_do._all_arrays[:, 0] =
|
|
548
|
+
scaled_do._all_arrays[:, 0] = (
|
|
549
|
+
scaled_do._all_arrays[:, 0] * q_target_max / q_self_max
|
|
550
|
+
+ offset
|
|
551
|
+
)
|
|
490
552
|
return scaled_do
|
|
491
553
|
|
|
492
554
|
xtype = "q" if q is not None else "tth" if tth is not None else "d"
|
|
@@ -497,7 +559,9 @@ class DiffractionObject:
|
|
|
497
559
|
|
|
498
560
|
xindex_data = (np.abs(data[0] - xvalue)).argmin()
|
|
499
561
|
xindex_target = (np.abs(target[0] - xvalue)).argmin()
|
|
500
|
-
scaled_do._all_arrays[:, 0] =
|
|
562
|
+
scaled_do._all_arrays[:, 0] = (
|
|
563
|
+
data[1] * target[1][xindex_target] / data[1][xindex_data] + offset
|
|
564
|
+
)
|
|
501
565
|
return scaled_do
|
|
502
566
|
|
|
503
567
|
def on_xtype(self, xtype):
|
|
@@ -506,7 +570,8 @@ class DiffractionObject:
|
|
|
506
570
|
Parameters
|
|
507
571
|
----------
|
|
508
572
|
xtype : str
|
|
509
|
-
The type of quantity for the independent variable chosen from
|
|
573
|
+
The type of quantity for the independent variable chosen from
|
|
574
|
+
{*XQUANTITIES, }
|
|
510
575
|
|
|
511
576
|
Raises
|
|
512
577
|
------
|
|
@@ -516,7 +581,8 @@ class DiffractionObject:
|
|
|
516
581
|
Returns
|
|
517
582
|
-------
|
|
518
583
|
(xarray, yarray) : tuple of ndarray
|
|
519
|
-
The tuple containing two 1D numpy arrays with x and y data for
|
|
584
|
+
The tuple containing two 1D numpy arrays with x and y data for
|
|
585
|
+
the specified xtype.
|
|
520
586
|
"""
|
|
521
587
|
if xtype.lower() in ANGLEQUANTITIES:
|
|
522
588
|
return self.on_tth()
|
|
@@ -536,12 +602,13 @@ class DiffractionObject:
|
|
|
536
602
|
filepath : str
|
|
537
603
|
The filepath where the diffraction object will be dumped
|
|
538
604
|
xtype : str, optional, default is q
|
|
539
|
-
The type of quantity for the independent variable chosen from
|
|
605
|
+
The type of quantity for the independent variable chosen from
|
|
606
|
+
{*XQUANTITIES, }
|
|
540
607
|
|
|
541
608
|
Examples
|
|
542
609
|
--------
|
|
543
|
-
To save a diffraction object to a file named "diffraction_data.chi"
|
|
544
|
-
with the independent variable 'q':
|
|
610
|
+
To save a diffraction object to a file named "diffraction_data.chi"
|
|
611
|
+
in the current directory with the independent variable 'q':
|
|
545
612
|
|
|
546
613
|
>>> file = "diffraction_data.chi"
|
|
547
614
|
>>> do.dump(file, xtype="q")
|
|
@@ -551,7 +618,8 @@ class DiffractionObject:
|
|
|
551
618
|
>>> file = "./output/diffraction_data.chi"
|
|
552
619
|
>>> do.dump(file, xtype="q")
|
|
553
620
|
|
|
554
|
-
To save the diffraction data with a different independent variable,
|
|
621
|
+
To save the diffraction data with a different independent variable,
|
|
622
|
+
such as 'tth':
|
|
555
623
|
|
|
556
624
|
>>> file = "diffraction_data_tth.chi"
|
|
557
625
|
>>> do.dump(file, xtype="tth")
|
|
@@ -561,17 +629,23 @@ class DiffractionObject:
|
|
|
561
629
|
if xtype in QQUANTITIES:
|
|
562
630
|
data_to_save = np.column_stack((self.on_q()[0], self.on_q()[1]))
|
|
563
631
|
elif xtype in ANGLEQUANTITIES:
|
|
564
|
-
data_to_save = np.column_stack(
|
|
632
|
+
data_to_save = np.column_stack(
|
|
633
|
+
(self.on_tth()[0], self.on_tth()[1])
|
|
634
|
+
)
|
|
565
635
|
elif xtype in DQUANTITIES:
|
|
566
636
|
data_to_save = np.column_stack((self.on_d()[0], self.on_d()[1]))
|
|
567
637
|
else:
|
|
568
638
|
warnings.warn(_xtype_wmsg(xtype))
|
|
569
|
-
self.metadata.update(
|
|
639
|
+
self.metadata.update(
|
|
640
|
+
get_package_info("diffpy.utils", metadata=self.metadata)
|
|
641
|
+
)
|
|
570
642
|
self.metadata["creation_time"] = datetime.datetime.now()
|
|
571
643
|
|
|
572
644
|
with open(filepath, "w") as f:
|
|
573
645
|
f.write(
|
|
574
|
-
f"[DiffractionObject]\
|
|
646
|
+
f"[DiffractionObject]\n"
|
|
647
|
+
f"name = {self.name}\n"
|
|
648
|
+
f"wavelength = {self.wavelength}\n"
|
|
575
649
|
f"scat_quantity = {self.scat_quantity}\n"
|
|
576
650
|
)
|
|
577
651
|
for key, value in self.metadata.items():
|
|
@@ -585,6 +659,7 @@ class DiffractionObject:
|
|
|
585
659
|
Returns
|
|
586
660
|
-------
|
|
587
661
|
DiffractionObject
|
|
588
|
-
The new instance of DiffractionObject, which is a deep copy of
|
|
662
|
+
The new instance of DiffractionObject, which is a deep copy of
|
|
663
|
+
the current instance.
|
|
589
664
|
"""
|
|
590
665
|
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]
|