From 13af9e2a2470778d5f57eec634f6df0cc1c527d0 Mon Sep 17 00:00:00 2001 From: Sangjoon Bob Lee Date: Mon, 30 Dec 2024 22:03:43 -0500 Subject: [PATCH 1/4] docs: improve docstring based on group standards in diffraction_objects.py transforms.py --- doc/source/api/diffpy.utils.parsers.rst | 16 ++-- doc/source/api/diffpy.utils.rst | 26 ++++-- news/docstrings-refactor.rst | 23 +++++ src/diffpy/utils/diffraction_objects.py | 119 +++++++++++++++++------- src/diffpy/utils/tools.py | 39 ++++---- src/diffpy/utils/transforms.py | 56 +++++------ 6 files changed, 180 insertions(+), 99 deletions(-) create mode 100644 news/docstrings-refactor.rst diff --git a/doc/source/api/diffpy.utils.parsers.rst b/doc/source/api/diffpy.utils.parsers.rst index 3456f24e..29ec4782 100644 --- a/doc/source/api/diffpy.utils.parsers.rst +++ b/doc/source/api/diffpy.utils.parsers.rst @@ -11,14 +11,6 @@ diffpy.utils.parsers package Submodules ---------- -diffpy.utils.parsers.serialization module -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. automodule:: diffpy.utils.parsers.serialization - :members: - :undoc-members: - :show-inheritance: - diffpy.utils.parsers.loaddata module ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,3 +26,11 @@ diffpy.utils.parsers.custom_exceptions module :members: :undoc-members: :show-inheritance: + +diffpy.utils.parsers.serialization module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: diffpy.utils.parsers.serialization + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/api/diffpy.utils.rst b/doc/source/api/diffpy.utils.rst index 2513e821..8073d8e6 100644 --- a/doc/source/api/diffpy.utils.rst +++ b/doc/source/api/diffpy.utils.rst @@ -16,30 +16,28 @@ Subpackages diffpy.utils.parsers diffpy.utils.wx - diffpy.utils.scattering_objects Submodules ---------- -diffpy.utils.tools module -^^^^^^^^^^^^^^^^^^^^^^^^^ +diffpy.utils.transforms module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.utils.tools +.. automodule:: diffpy.utils.transforms :members: :undoc-members: :show-inheritance: -diffpy.utils.resampler module -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +diffpy.utils.tools module +^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: diffpy.utils.resampler +.. automodule:: diffpy.utils.tools :members: :undoc-members: :show-inheritance: - diffpy.utils.user_config module -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. automodule:: diffpy.utils.user_config :members: @@ -47,9 +45,17 @@ diffpy.utils.user_config module :show-inheritance: diffpy.utils.diffraction_objects module -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. automodule:: diffpy.utils.diffraction_objects :members: :undoc-members: :show-inheritance: + +diffpy.utils.resampler module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: diffpy.utils.resampler + :members: + :undoc-members: + :show-inheritance: diff --git a/news/docstrings-refactor.rst b/news/docstrings-refactor.rst new file mode 100644 index 00000000..0dca3d1d --- /dev/null +++ b/news/docstrings-refactor.rst @@ -0,0 +1,23 @@ +**Added:** + +* No news added: this branch was used to refactor the docstrings in the codebase without adding new features + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* diff --git a/src/diffpy/utils/diffraction_objects.py b/src/diffpy/utils/diffraction_objects.py index 9e56e0d3..ce43a831 100644 --- a/src/diffpy/utils/diffraction_objects.py +++ b/src/diffpy/utils/diffraction_objects.py @@ -92,18 +92,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 ... @@ -180,30 +180,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 """ @@ -218,6 +220,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)): @@ -229,6 +246,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)): @@ -240,6 +272,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)): @@ -288,7 +334,7 @@ def input_xtype(self): Returns ------- - str + input_xtype : str The type of `xarray`, which must be one of {*XQUANTITIES}. """ return self._input_xtype @@ -303,7 +349,7 @@ def uuid(self): Returns ------- - uuid + uuid : UUID The unique identifier of the DiffractionObject instance. """ return self._uuid @@ -325,7 +371,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. """ @@ -378,7 +424,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. @@ -400,12 +446,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( @@ -416,8 +462,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) @@ -427,21 +473,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 + A tuple containing two 1D numpy arrays with x and y data for the specified xtype. """ if xtype.lower() in ANGLEQUANTITIES: return self.on_tth() @@ -482,6 +533,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..f3c169a6 100644 --- a/src/diffpy/utils/transforms.py +++ b/src/diffpy/utils/transforms.py @@ -28,7 +28,7 @@ def _validate_inputs(q, wavelength): raise ValueError(invalid_q_or_d_or_wavelength_emsg) -def q_to_tth(q, wavelength): +def q_to_tth(q, wavelength) -> np.ndarray: r"""Helper function to convert q to two-theta. If wavelength is missing, returns x-values that are integer indexes @@ -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) From ee5f3a3b0fb206b1633f013fa074664accf8af96 Mon Sep 17 00:00:00 2001 From: Sangjoon Bob Lee Date: Mon, 30 Dec 2024 22:09:29 -0500 Subject: [PATCH 2/4] chore: fix from a tuple to The tuple in docstring --- src/diffpy/utils/diffraction_objects.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/diffpy/utils/diffraction_objects.py b/src/diffpy/utils/diffraction_objects.py index ce43a831..cc9a92a6 100644 --- a/src/diffpy/utils/diffraction_objects.py +++ b/src/diffpy/utils/diffraction_objects.py @@ -492,7 +492,7 @@ def on_xtype(self, xtype): Returns ------- (xarray, yarray) : tuple of ndarray - A tuple containing two 1D numpy arrays with x and y data for the specified xtype. + 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() From f29ad9195c576447d7ba96a8ee92fd5db0b46803 Mon Sep 17 00:00:00 2001 From: Sangjoon Bob Lee Date: Mon, 30 Dec 2024 22:42:19 -0500 Subject: [PATCH 3/4] chore: removed np.nsarray return type, not needed --- src/diffpy/utils/transforms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/diffpy/utils/transforms.py b/src/diffpy/utils/transforms.py index f3c169a6..21c069b1 100644 --- a/src/diffpy/utils/transforms.py +++ b/src/diffpy/utils/transforms.py @@ -28,7 +28,7 @@ def _validate_inputs(q, wavelength): raise ValueError(invalid_q_or_d_or_wavelength_emsg) -def q_to_tth(q, wavelength) -> np.ndarray: +def q_to_tth(q, wavelength): r"""Helper function to convert q to two-theta. If wavelength is missing, returns x-values that are integer indexes From 5dfff333783e6a2f2a0a30b70834372851bac87e Mon Sep 17 00:00:00 2001 From: Sangjoon Bob Lee Date: Tue, 31 Dec 2024 09:28:20 -0500 Subject: [PATCH 4/4] chore: added news for docstring --- news/docstrings-refactor.rst | 2 +- src/diffpy/utils/diffraction_objects.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/news/docstrings-refactor.rst b/news/docstrings-refactor.rst index 0dca3d1d..203b036e 100644 --- a/news/docstrings-refactor.rst +++ b/news/docstrings-refactor.rst @@ -1,6 +1,6 @@ **Added:** -* No news added: this branch was used to refactor the docstrings in the codebase without adding new features +* Improved API documentation in `DiffractionObject` methods and properties using the NumPy docstring format and PEP 256 **Changed:** diff --git a/src/diffpy/utils/diffraction_objects.py b/src/diffpy/utils/diffraction_objects.py index 2f4dfa8b..f95f1758 100644 --- a/src/diffpy/utils/diffraction_objects.py +++ b/src/diffpy/utils/diffraction_objects.py @@ -190,7 +190,7 @@ def __add__(self, other): Returns ------- DiffractionObject - THe new DiffractionObject instance with modified yarray values. This instance is a deep copy of the + The new DiffractionObject instance with modified yarray values. This instance is a deep copy of the original with the additions applied. Raises