-
Notifications
You must be signed in to change notification settings - Fork 21
Do not allow an empty instance of DiffractionObject - require xarrays
yarrays
xtype
#228
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 15 commits
92a2c4c
56541e5
1144d1f
e7b4dc2
6dc2738
50b7d0d
291cc89
b8a9adc
e3c5208
db89596
de6f12d
7ccebe8
2752578
d1f767b
afe814b
46c7be8
d24aacd
e285214
4f54439
7a2603e
8693153
e68b59e
235f624
88ea61b
6b20c1a
9f0f11a
aa1af39
d09d7fb
0e362c1
c142240
24b1bbc
2c51af1
ba4b985
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,27 +35,82 @@ def _setter_wmsg(attribute): | |
|
||
|
||
class DiffractionObject: | ||
""" | ||
Initialize a DiffractionObject instance. | ||
|
||
Parameters | ||
---------- | ||
xarray : array-like | ||
The independent variable array containing "q", "tth", or "d" values. | ||
yarray : array-like | ||
The dependent variable array corresponding to intensity values. | ||
xtype : str | ||
The type of the independent variable in `xarray`. Must be one of {*XQUANTITIES}. | ||
wavelength : float, optional | ||
The wavelength of the incoming beam, specified in angstroms (Å). Default is none. | ||
scat_quantity : str, optional | ||
The type of scattering experiment (e.g., "x-ray", "neutron"). Default is an empty string "". | ||
name : str, optional | ||
The name or label for the scattering data. Default is an empty string "". | ||
metadata : dict, optional | ||
The additional metadata associated with the diffraction object. Default is {}. | ||
|
||
Examples | ||
-------- | ||
Create a DiffractionObject for X-ray scattering data: | ||
|
||
>>> import numpy as np | ||
>>> from diffpy.utils.diffraction_objects import DiffractionObject | ||
... | ||
>>> x = np.array([0.12, 0.24, 0.31, 0.4]) # independent variable (e.g., q) | ||
>>> y = np.array([10, 20, 40, 60]) # intensity values | ||
>>> metadata = { | ||
... "package_info": {"version": "3.6.0"} | ||
... } | ||
>>> do = DiffractionObject( | ||
... xarray=x, | ||
... yarray=y, | ||
... xtype="q", | ||
... wavelength=1.54, | ||
... scat_quantity="x-ray", | ||
... metadata=metadata | ||
sbillinge marked this conversation as resolved.
Show resolved
Hide resolved
|
||
... ) | ||
>>> print(do.metadata) | ||
""" | ||
bobleesj marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
def __init__( | ||
self, name=None, wavelength=None, scat_quantity=None, metadata=None, xarray=None, yarray=None, xtype=None | ||
self, | ||
xarray, | ||
yarray, | ||
xtype, | ||
wavelength=None, | ||
scat_quantity="", | ||
sbillinge marked this conversation as resolved.
Show resolved
Hide resolved
|
||
name="", | ||
metadata={}, | ||
): | ||
if name is None: | ||
name = "" | ||
self.name = name | ||
if metadata is None: | ||
metadata = {} | ||
self.metadata = metadata | ||
if xtype is None: | ||
xtype = "" | ||
self.scat_quantity = scat_quantity | ||
self.wavelength = wavelength | ||
|
||
if xarray is None: | ||
xarray = np.empty(0) | ||
if yarray is None: | ||
yarray = np.empty(0) | ||
|
||
self._id = uuid.uuid4() | ||
self.input_data(xarray, yarray, xtype) | ||
self._input_data(xarray, yarray, xtype, wavelength, scat_quantity, name, metadata) | ||
|
||
def _input_data(self, xarray, yarray, xtype, wavelength, scat_quantity, name, metadata): | ||
if xtype not in XQUANTITIES: | ||
raise ValueError(_xtype_wmsg(xtype)) | ||
|
||
sbillinge marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# Check xarray and yarray have the same length | ||
if len(xarray) != len(yarray): | ||
raise ValueError( | ||
"'xarray' and 'yarray' must have the same length. " | ||
"Please re-initialize 'DiffractionObject' or re-run the method 'input_data' " | ||
"with 'xarray' and 'yarray' of identical length." | ||
) | ||
|
||
sbillinge marked this conversation as resolved.
Show resolved
Hide resolved
|
||
self.scat_quantity = scat_quantity | ||
self.wavelength = wavelength | ||
self.metadata = metadata | ||
self.name = name | ||
self._input_xtype = xtype | ||
self._set_arrays(xarray, xtype, yarray) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. as discussed - private func |
||
self._set_min_max_xarray() | ||
|
||
def __eq__(self, other): | ||
if not isinstance(other, DiffractionObject): | ||
|
@@ -298,16 +353,16 @@ def get_array_index(self, value, xtype=None): | |
the index of the value in the array | ||
""" | ||
|
||
if xtype is None: | ||
xtype = self._input_xtype | ||
xtype = self._input_xtype | ||
array = self.on_xtype(xtype)[0] | ||
if len(array) == 0: | ||
raise ValueError(f"The '{xtype}' array is empty. Please ensure it is initialized.") | ||
i = (np.abs(array - value)).argmin() | ||
return i | ||
|
||
def _set_xarrays(self, xarray, xtype): | ||
def _set_arrays(self, xarray, xtype, yarray): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe we should stay consistent...x, y, xtype order? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
self._all_arrays = np.empty(shape=(len(xarray), 4)) | ||
self._all_arrays[:, 0] = yarray | ||
if xtype.lower() in QQUANTITIES: | ||
self._all_arrays[:, 1] = xarray | ||
self._all_arrays[:, 2] = q_to_tth(xarray, self.wavelength) | ||
|
@@ -320,70 +375,15 @@ def _set_xarrays(self, xarray, xtype): | |
self._all_arrays[:, 3] = xarray | ||
self._all_arrays[:, 1] = d_to_q(xarray) | ||
self._all_arrays[:, 2] = d_to_tth(xarray, self.wavelength) | ||
|
||
def _set_min_max_xarray(self): | ||
sbillinge marked this conversation as resolved.
Show resolved
Hide resolved
|
||
self.qmin = np.nanmin(self._all_arrays[:, 1], initial=np.inf) | ||
self.qmax = np.nanmax(self._all_arrays[:, 1], initial=0.0) | ||
self.tthmin = np.nanmin(self._all_arrays[:, 2], initial=np.inf) | ||
self.tthmax = np.nanmax(self._all_arrays[:, 2], initial=0.0) | ||
self.dmin = np.nanmin(self._all_arrays[:, 3], initial=np.inf) | ||
self.dmax = np.nanmax(self._all_arrays[:, 3], initial=0.0) | ||
|
||
def input_data( | ||
self, | ||
xarray, | ||
yarray, | ||
xtype, | ||
metadata={}, | ||
scat_quantity=None, | ||
name=None, | ||
wavelength=None, | ||
): | ||
f""" | ||
insert a new scattering quantity into the scattering object | ||
|
||
Parameters | ||
---------- | ||
xarray array-like of floats | ||
the independent variable array | ||
yarray array-like of floats | ||
the dependent variable array | ||
xtype string | ||
the type of quantity for the independent variable from {*XQUANTITIES, } | ||
metadata, scat_quantity, name and wavelength are optional. They have the same | ||
meaning as in the constructor. Values will only be overwritten if non-empty values are passed. | ||
|
||
Returns | ||
------- | ||
Nothing. Updates the object in place. | ||
|
||
""" | ||
|
||
# Check xarray and yarray have the same length | ||
if len(xarray) != len(yarray): | ||
raise ValueError( | ||
"'xarray' and 'yarray' must have the same length. " | ||
"Please re-initialize 'DiffractionObject' or re-run the method 'input_data' " | ||
"with 'xarray' and 'yarray' of identical length." | ||
) | ||
|
||
self._set_xarrays(xarray, xtype) | ||
self._all_arrays[:, 0] = yarray | ||
self._input_xtype = xtype | ||
# only update these optional values if non-empty quantities are passed to avoid overwriting | ||
# valid data inadvertently | ||
if metadata: | ||
self.metadata = metadata | ||
if scat_quantity is not None: | ||
self.scat_quantity = scat_quantity | ||
if name is not None: | ||
self.name = name | ||
if wavelength is not None: | ||
self.wavelength = wavelength | ||
|
||
# Check xtype is valid. An empty string is the default value. | ||
if xtype != "": | ||
if xtype not in XQUANTITIES: | ||
raise ValueError(_xtype_wmsg(xtype)) | ||
|
||
def _get_original_array(self): | ||
if self._input_xtype in QQUANTITIES: | ||
return self.on_q(), "q" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this could only have been come up with by a programmer. Could we instead have an example of what we are after from materials scientists. Model some good behavior. Something like
metadata = {'sample': "rock salt from the beach", "composition": "NaCl", "temperature": "300 K,", "experimenters": "Phill, Sally" }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done