Skip to content
Prev Previous commit
Next Next commit
test: writting better docstrings and comments
  • Loading branch information
Luiskitsu committed Apr 11, 2025
commit ead324881156de78908e20e0adf601244c5e6a44
27 changes: 24 additions & 3 deletions src/diffpy/morph/morphs/morphsqueeze.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,29 @@ class MorphSqueeze(Morph):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it may be nice to have a usage example in the docstring. Basically copy-paste the code from the test to show how the morph can be instantiated and then used.

We normally put docstrings in the methods and in the constructor (the def __init__():). This class is inheriting the constructor from the base class, so I am not 100% sure how the docstring propagates through in the documentation, but without that, but I think if we put a docstring under the def morph(): which is overloading that method from the base class, it should become clear.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I was following the architecture of other morphs. They have a docstring bellow the class which is the main description and then another docstring under the function which are few words. Should I keep it consistent?
When I add an example in the docstring do I add it as code using >>>?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't have a group standard for this, but more recently I think we are leaning towards having the class-level docstring to be just a few words about the high level intent of the class and the docstring of the constructor to be have more detail. I did look into this question at one point and formed an opinion, but I don't fully remember what I found. It could have been when I was working on my beloved "DiffractionObject"s in diffpy.utils but I am not sure. We could look there. All documentation is better than lack of documentation, so the standards are just for us to figure out the most effective (user-useful) way to write the docs so that any time we spend on it has the most impact.

Configuration Variables
-----------------------
squeeze
list or array-like
Polynomial coefficients [a0, a1, ..., an] for the squeeze function.
squeeze : list
The polynomial coefficients [a0, a1, ..., an] for the squeeze function
where the polynomial would be of the form a0 + a1*x + a2*x^2 and so
on. The order of the polynomial is determined by the length of the
list.

Example
-------
>>> import numpy as np
>>> from numpy.polynomial import Polynomial
>>> from diffpy.morph.morphs.morphsqueeze import MorphSqueeze

>>> x_morph = np.linspace(0, 10, 101)
>>> x_target = np.linspace(0, 10, 101)
>>> squeeze_coeff = [0.1, -0.01, 0.005]
>>> poly = Polynomial(squeeze_coeff)
>>> y_morph = np.sin(x_morph + poly(x_morph))
>>> y_target = np.sin(x_target)

>>> morph = MorphSqueeze()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this block is what we are after. We could add a few words about what the variables mean. Maybe also add a couple of lines that show other attributes that the user can access from the morph instance. For example things like
x_morph_in = morph.x_morph_in etc. No need to be exhaustive, just give a few examples to help users.

btw, this looks great in general. I am not sure if we have a "group standard" for these code blocks. I think that it is possible to write htese actually so that they can be run by some automated testing codes but we don't really do that. I just feel that, as a user, if there is a few lines of code showing how to use this, it can be super helpful.

>>> morph.squeeze = squeeze_coeff
>>> x_morph_out, y_morph_out, x_target_out, y_target_out = morph(
... x_morph, y_morph, x_target, y_target)
"""

# Define input output types
Expand All @@ -23,6 +43,7 @@ class MorphSqueeze(Morph):
parnames = ["squeeze"]

def morph(self, x_morph, y_morph, x_target, y_target):
"""Apply a polynomial to squeeze the morph function"""
Morph.morph(self, x_morph, y_morph, x_target, y_target)

return self.xyallout
12 changes: 6 additions & 6 deletions tests/test_morphsqueeze.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,17 @@
]
morph_target_grids = [
# UCs from issue 181: https://github.com/diffpy/diffpy.morph/issues/181
# UC2: Same grid
# UC2: Same range and same grid density

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now fantastic! I love these tests. Future us will love you.

(np.linspace(0, 10, 101), np.linspace(0, 10, 101)),
# UC4: Target extends beyond morph
# UC4: Target range wider than morph, same grid density
(np.linspace(0, 10, 101), np.linspace(-2, 20, 221)),
# UC6: Target extends beyond morph; morph coarser
# UC6: Target range wider than morph, finer target grid density
(np.linspace(0, 10, 101), np.linspace(-2, 20, 421)),
# UC8: Target extends beyond morph; target coarser
# UC8: Target range wider than morph, finer morph grid density
(np.linspace(0, 10, 401), np.linspace(-2, 20, 200)),
# UC10: morph starts earlier than target
# UC10: Morph range starts and ends earlier than target, same grid density
(np.linspace(-2, 10, 121), np.linspace(0, 20, 201)),
# UC12: morph extends beyond target
# UC12: Morph range wider than target, same grid density
(np.linspace(-2, 20, 221), np.linspace(0, 10, 101)),
]

Expand Down