diff --git a/news/docstrings-refactor.rst b/news/docstrings-refactor.rst new file mode 100644 index 00000000..203b036e --- /dev/null +++ b/news/docstrings-refactor.rst @@ -0,0 +1,23 @@ +**Added:** + +* Improved API documentation in `DiffractionObject` methods and properties using the NumPy docstring format and PEP 256 + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* diff --git a/src/diffpy/utils/diffraction_objects.py b/src/diffpy/utils/diffraction_objects.py index 5c5cd7e2..f95f1758 100644 --- a/src/diffpy/utils/diffraction_objects.py +++ b/src/diffpy/utils/diffraction_objects.py @@ -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 ... @@ -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 """ @@ -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)): @@ -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)): @@ -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)): @@ -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 @@ -306,7 +352,7 @@ def uuid(self): Returns ------- - uuid + uuid : UUID The unique identifier of the DiffractionObject instance. """ return self._uuid @@ -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. """ @@ -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. @@ -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( @@ -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) @@ -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() @@ -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) diff --git a/src/diffpy/utils/tools.py b/src/diffpy/utils/tools.py index 036cc696..61868072 100644 --- a/src/diffpy/utils/tools.py +++ b/src/diffpy/utils/tools.py @@ -11,20 +11,20 @@ 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): @@ -32,12 +32,12 @@ def _load_config(file_path): 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() @@ -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'. @@ -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. """ @@ -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 @@ -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" @@ -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'}}. @@ -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: diff --git a/src/diffpy/utils/transforms.py b/src/diffpy/utils/transforms.py index f2956879..21c069b1 100644 --- a/src/diffpy/utils/transforms.py +++ b/src/diffpy/utils/transforms.py @@ -47,8 +47,8 @@ def q_to_tth(q, wavelength): Parameters ---------- - q : 1D array - The array of :math:`q` values numpy.array([qs]). + q : ndarray + The 1D array of :math:`q` values numpy.array([qs]). The units of q must be reciprocal of the units of wavelength. wavelength : float @@ -56,8 +56,8 @@ def q_to_tth(q, wavelength): Returns ------- - tth : 1D array - The array of :math:`2\theta` values in degrees numpy.array([tths]). + tth : ndarray + The 1D array of :math:`2\theta` values in degrees numpy.array([tths]). """ _validate_inputs(q, wavelength) q.astype(float) @@ -89,17 +89,17 @@ def tth_to_q(tth, wavelength): Parameters ---------- - tth : 1D array - The array of :math:`2\theta` values np.array([tths]). + tth : ndarray + The 1D array of :math:`2\theta` values np.array([tths]). The units of tth are expected in degrees. wavelength : float - Wavelength of the incoming x-rays/neutrons/electrons + The wavelength of the incoming x-rays/neutrons/electrons. Returns ------- - q : 1D array - The array of :math:`q` values np.array([qs]). + q : ndarray + The 1D array of :math:`q` values np.array([qs]). The units for the q-values are the inverse of the units of the provided wavelength. """ tth.astype(float) @@ -122,14 +122,14 @@ def q_to_d(q): Parameters ---------- - q : 1D array - The array of :math:`q` values np.array([qs]). + q : ndarray + The 1D array of :math:`q` values np.array([qs]). The units of q must be reciprocal of the units of wavelength. Returns ------- - d : 1D array - The array of :math:`d` values np.array([ds]). + d : ndarray + The 1D array of :math:`d` values np.array([ds]). """ if 0 in q: print(inf_output_imsg) @@ -145,17 +145,17 @@ def tth_to_d(tth, wavelength): Parameters ---------- - tth : 1D array - The array of :math:`2\theta` values np.array([tths]). + tth : nsarray + The 1D array of :math:`2\theta` values np.array([tths]). The units of tth are expected in degrees. wavelength : float - Wavelength of the incoming x-rays/neutrons/electrons + The wavelength of the incoming x-rays/neutrons/electrons. Returns ------- - d : 1D array - The array of :math:`d` values np.array([ds]). + d : nsarray + The 1D array of :math:`d` values np.array([ds]). """ q = tth_to_q(tth, wavelength) d = copy(tth) @@ -174,13 +174,13 @@ def d_to_q(d): Parameters ---------- - d : 1D array - The array of :math:`d` values np.array([ds]). + d : nsarray + The 1D array of :math:`d` values np.array([ds]). Returns ------- - q : 1D array - The array of :math:`q` values np.array([qs]). + q : nsarray + The 1D array of :math:`q` values np.array([qs]). The units of q must be reciprocal of the units of wavelength. """ if 0 in d: @@ -197,16 +197,16 @@ def d_to_tth(d, wavelength): Parameters ---------- - d : 1D array - The array of :math:`d` values np.array([ds]). + d : nsarray + The 1D array of :math:`d` values np.array([ds]). wavelength : float - Wavelength of the incoming x-rays/neutrons/electrons + The wavelength of the incoming x-rays/neutrons/electrons. Returns ------- - tth : 1D array - The array of :math:`2\theta` values np.array([tths]). + tth : nsarray + The 1D array of :math:`2\theta` values np.array([tths]). The units of tth are expected in degrees. """ q = d_to_q(d)