Skip to content

Commit

Permalink
Merge pull request #300 from bobleesj/docstrings-overview
Browse files Browse the repository at this point in the history
docs: improve docstring based on group standards in diffraction_objects.py transforms.py
  • Loading branch information
sbillinge authored Dec 31, 2024
2 parents 52f1c79 + 5dfff33 commit 0a3241b
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 80 deletions.
23 changes: 23 additions & 0 deletions news/docstrings-refactor.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
**Added:**

* Improved API documentation in `DiffractionObject` methods and properties using the NumPy docstring format and PEP 256

**Changed:**

* <news item>

**Deprecated:**

* <news item>

**Removed:**

* <news item>

**Fixed:**

* <news item>

**Security:**

* <news item>
119 changes: 85 additions & 34 deletions src/diffpy/utils/diffraction_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,18 +93,18 @@ def __init__(
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 {}.
wavelength : float, optional, default is None.
The wavelength of the incoming beam, specified in angstroms (Å)
scat_quantity : str, optional, default is an empty string "".
The type of scattering experiment (e.g., "x-ray", "neutron").
name : str, optional, default is an empty string "".
The name or label for the scattering data.
metadata : dict, optional, default is an empty dictionary {}
The additional metadata associated with the diffraction object.
Examples
--------
Create a DiffractionObject for X-ray scattering data
Create a DiffractionObject for X-ray scattering data:
>>> import numpy as np
>>> from diffpy.utils.diffraction_objects import DiffractionObject
...
Expand Down Expand Up @@ -181,30 +181,32 @@ def __add__(self, other):
Parameters
----------
other : DiffractionObject or int or float
The object to add to the current DiffractionObject. If `other` is a scalar value,
it will be added to all yarray. The length of the yarray must match if `other` is
an instance of DiffractionObject.
other : DiffractionObject, int, or float
The item to be added. If `other` is a scalar value, this value will be added to each element of the
yarray of this DiffractionObject instance. If `other` is another DiffractionObject, the yarrays of the
two DiffractionObjects will be combined element-wise. The result is a new DiffractionObject instance,
representing the addition and using the xarray from the left-hand side DiffractionObject.
Returns
-------
DiffractionObject
The new and deep-copied DiffractionObject instance after adding values to the yarray.
The new DiffractionObject instance with modified yarray values. This instance is a deep copy of the
original with the additions applied.
Raises
------
ValueError
Raised when the length of the yarray of the two DiffractionObject instances do not match.
Raised when the xarrays of two DiffractionObject instances are not equal.
TypeError
Raised when the type of `other` is not an instance of DiffractionObject, int, or float.
Raised when `other` is not an instance of DiffractionObject, int, or float.
Examples
--------
Add a scalar value to the yarray of the DiffractionObject instance:
Add a scalar value to the yarray of a DiffractionObject instance:
>>> new_do = my_do + 10.1
>>> new_do = 10.1 + my_do
Add the yarray of two DiffractionObject instances:
Combine the yarrays of two DiffractionObject instances:
>>> new_do = my_do_1 + my_do_2
"""

Expand All @@ -219,6 +221,21 @@ def __add__(self, other):
__radd__ = __add__

def __sub__(self, other):
"""Subtract scalar value or another DiffractionObject to the yarray of
the DiffractionObject.
This method behaves similarly to the `__add__` method, but performs subtraction instead of addition.
For details on parameters, returns, and exceptions, refer to the documentation for `__add__`.
Examples
--------
Subtract a scalar value from the yarray of a DiffractionObject instance:
>>> new_do = my_do - 10.1
Subtract the yarrays of two DiffractionObject instances:
>>> new_do = my_do_1 - my_do_2
"""

self._check_operation_compatibility(other)
subtracted_do = deepcopy(self)
if isinstance(other, (int, float)):
Expand All @@ -230,6 +247,21 @@ def __sub__(self, other):
__rsub__ = __sub__

def __mul__(self, other):
"""Multiply a scalar value or another DiffractionObject with the yarray
of this DiffractionObject.
This method behaves similarly to the `__add__` method, but performs multiplication instead of addition.
For details on parameters, returns, and exceptions, refer to the documentation for `__add__`.
Examples
--------
Multiply a scalar value with the yarray of a DiffractionObject instance:
>>> new_do = my_do * 3.5
Multiply the yarrays of two DiffractionObject instances:
>>> new_do = my_do_1 * my_do_2
"""

self._check_operation_compatibility(other)
multiplied_do = deepcopy(self)
if isinstance(other, (int, float)):
Expand All @@ -241,6 +273,20 @@ def __mul__(self, other):
__rmul__ = __mul__

def __truediv__(self, other):
"""Divide the yarray of this DiffractionObject by a scalar value or
another DiffractionObject.
This method behaves similarly to the `__add__` method, but performs division instead of addition.
For details on parameters, returns, and exceptions, refer to the documentation for `__add__`.
Examples
--------
Divide the yarray of a DiffractionObject instance by a scalar value:
>>> new_do = my_do / 2.0
Divide the yarrays of two DiffractionObject instances:
>>> new_do = my_do_1 / my_do_2
"""
self._check_operation_compatibility(other)
divided_do = deepcopy(self)
if isinstance(other, (int, float)):
Expand Down Expand Up @@ -291,7 +337,7 @@ def input_xtype(self):
Returns
-------
str
input_xtype : str
The type of `xarray`, which must be one of {*XQUANTITIES}.
"""
return self._input_xtype
Expand All @@ -306,7 +352,7 @@ def uuid(self):
Returns
-------
uuid
uuid : UUID
The unique identifier of the DiffractionObject instance.
"""
return self._uuid
Expand All @@ -328,7 +374,7 @@ def get_array_index(self, xtype, xvalue):
Returns
-------
int
index : int
The index of the closest value in the array associated with the specified xtype and the value provided.
"""

Expand Down Expand Up @@ -381,7 +427,7 @@ def on_d(self):
return [self.all_arrays[:, 3], self.all_arrays[:, 0]]

def scale_to(self, target_diff_object, q=None, tth=None, d=None, offset=None):
"""Returns a new diffraction object which is the current object but
"""Return a new diffraction object which is the current object but
rescaled in y to the target.
By default, if `q`, `tth`, or `d` are not provided, scaling is based on the max intensity from each object.
Expand All @@ -403,12 +449,12 @@ def scale_to(self, target_diff_object, q=None, tth=None, d=None, offset=None):
Returns
-------
scaled : DiffractionObject
scaled_do : DiffractionObject
The rescaled DiffractionObject as a new object.
"""
if offset is None:
offset = 0
scaled = self.copy()
scaled_do = self.copy()
count = sum([q is not None, tth is not None, d is not None])
if count > 1:
raise ValueError(
Expand All @@ -419,8 +465,8 @@ def scale_to(self, target_diff_object, q=None, tth=None, d=None, offset=None):
if count == 0:
q_target_max = max(target_diff_object.on_q()[1])
q_self_max = max(self.on_q()[1])
scaled._all_arrays[:, 0] = scaled._all_arrays[:, 0] * q_target_max / q_self_max + offset
return scaled
scaled_do._all_arrays[:, 0] = scaled_do._all_arrays[:, 0] * q_target_max / q_self_max + offset
return scaled_do

xtype = "q" if q is not None else "tth" if tth is not None else "d"
data = self.on_xtype(xtype)
Expand All @@ -430,21 +476,26 @@ def scale_to(self, target_diff_object, q=None, tth=None, d=None, offset=None):

xindex_data = (np.abs(data[0] - xvalue)).argmin()
xindex_target = (np.abs(target[0] - xvalue)).argmin()
scaled._all_arrays[:, 0] = data[1] * target[1][xindex_target] / data[1][xindex_data] + offset
return scaled
scaled_do._all_arrays[:, 0] = data[1] * target[1][xindex_target] / data[1][xindex_data] + offset
return scaled_do

def on_xtype(self, xtype):
"""Return a list of two 1D np array with x and y data, raise an error
if the specified xtype is invalid.
"""Return a tuple of two 1D numpy arrays containing x and y data.
Parameters
----------
xtype str
the type of quantity for the independent variable from {*XQUANTITIES, }
xtype : str
The type of quantity for the independent variable chosen from {*XQUANTITIES, }
Raises
------
ValueError
Raised when the specified xtype is not among {*XQUANTITIES, }
Returns
-------
a list of two 1D np array with x and y data
(xarray, yarray) : tuple of ndarray
The tuple containing two 1D numpy arrays with x and y data for the specified xtype.
"""
if xtype.lower() in ANGLEQUANTITIES:
return self.on_tth()
Expand Down Expand Up @@ -485,6 +536,6 @@ def copy(self):
Returns
-------
DiffractionObject
A new instance of DiffractionObject, which is a deep copy of the current instance.
The new instance of DiffractionObject, which is a deep copy of the current instance.
"""
return deepcopy(self)
39 changes: 20 additions & 19 deletions src/diffpy/utils/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,33 @@
from diffpy.utils.parsers.loaddata import loadData


def _stringify(obj):
def _stringify(string_value):
"""Convert None to an empty string.
Parameters
----------
obj: str
The object to convert. If None, return an empty string.
string_value : str or None
The value to be converted. If None, an empty string is returned.
Returns
-------
str or None:
The converted string if obj is not None, otherwise an empty string.
str
The original string if string_value is not None, otherwise an empty string.
"""
return obj if obj is not None else ""
return string_value if string_value is not None else ""


def _load_config(file_path):
"""Load configuration from a .json file.
Parameters
----------
file_path: Path
file_path : Path
The path to the configuration file.
Returns
-------
dict:
config : dict
The configuration dictionary or {} if the config file does not exist.
"""
config_file = Path(file_path).resolve()
Expand All @@ -50,7 +50,7 @@ def _load_config(file_path):


def get_user_info(owner_name=None, owner_email=None, owner_orcid=None):
"""Get name, email and orcid of the owner/user from various sources and
"""Get name, email, and orcid of the owner/user from various sources and
return it as a metadata dictionary.
The function looks for the information in json format configuration files with the name 'diffpyconfig.json'.
Expand All @@ -71,16 +71,16 @@ def get_user_info(owner_name=None, owner_email=None, owner_orcid=None):
Parameters
----------
owner_name: string, optional, default is the value stored in the global or local config file.
owner_name : str, optional, default is the value stored in the global or local config file.
The name of the user who will show as owner in the metadata that is stored with the data
owner_email: string, optional, default is the value stored in the global or local config file.
owner_email : str, optional, default is the value stored in the global or local config file.
The email of the user/owner
owner_orcid: string, optional, default is the value stored in the global or local config file.
owner_orcid : str, optional, default is the value stored in the global or local config file.
The ORCID id of the user/owner
Returns
-------
dict:
user_info : dict
The dictionary containing username, email and orcid of the user/owner, and any other information
stored in the global or local config files.
"""
Expand All @@ -97,7 +97,7 @@ def get_user_info(owner_name=None, owner_email=None, owner_orcid=None):


def check_and_build_global_config(skip_config_creation=False):
"""Checks for a global diffpu config file in user's home directory and
"""Check for a global diffpu config file in user's home directory and
creates one if it is missing.
The file it looks for is called diffpyconfig.json. This can contain anything in json format, but
Expand All @@ -116,12 +116,13 @@ def check_and_build_global_config(skip_config_creation=False):
Parameters
----------
skip_config_creation: bool, optional, Default is False
The bool that will override the creation workflow even if no config file exists.
skip_config_creation : bool, optional, default is False.
The boolean that will override the creation workflow even if no config file exists.
Returns
-------
bool: True if the file exists and False otherwise.
config_exists : bool
The boolean indicating whether the config file exists.
"""
config_exists = False
config_path = Path().home() / "diffpyconfig.json"
Expand Down Expand Up @@ -168,7 +169,7 @@ def check_and_build_global_config(skip_config_creation=False):


def get_package_info(package_names, metadata=None):
"""Fetches package version and updates it into (given) metadata.
"""Fetch package version and updates it into (given) metadata.
Package info stored in metadata as {'package_info': {'package_name': 'version_number'}}.
Expand All @@ -180,7 +181,7 @@ def get_package_info(package_names, metadata=None):
Returns
-------
dict:
metadata : dict
The updated metadata dict with package info inserted.
"""
if metadata is None:
Expand Down
Loading

0 comments on commit 0a3241b

Please sign in to comment.