Skip to content

Commit d4b0079

Browse files
authored
Update docstrings for clarity (#273)
* Update tests * Docstring fixes
1 parent 561499b commit d4b0079

File tree

4 files changed

+120
-61
lines changed

4 files changed

+120
-61
lines changed

docs/source/morphpy.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,11 @@ verbose: bool
8787
Print additional header details to saved files. These include details about the morph
8888
inputs and outputs.
8989
xmin: float
90-
Minimum r-value (abscissa) to use for function comparisons.
90+
Minimum x-value (abscissa) to use for function comparisons.
9191
xmax: float
92-
Maximum r-value (abscissa) to use for function comparisons.
92+
Maximum x-value (abscissa) to use for function comparisons.
9393
tolerance: float
94-
Specify least squares refiner tolerance when optimizing for morph parameters. Default: 10e-8.
94+
Specify least squares refiner tolerance when optimizing for morph parameters. Default: 1e-8.
9595
pearson: bool
9696
The refiner instead maximizes agreement in the Pearson function
9797
(default behavior is to minimize the residual).

news/docstring.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
**Added:**
2+
3+
* <news item>
4+
5+
**Changed:**
6+
7+
* <news item>
8+
9+
**Deprecated:**
10+
11+
* <news item>
12+
13+
**Removed:**
14+
15+
* <news item>
16+
17+
**Fixed:**
18+
19+
* Docstrings updated for better clarity.
20+
21+
**Security:**
22+
23+
* <news item>

src/diffpy/morph/morphapp.py

Lines changed: 89 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ def custom_error(self, msg):
5252
parser = CustomParser(
5353
usage="\n".join(
5454
[
55-
"%prog [options] FILE1 FILE2",
56-
"Manipulate and compare PDFs.",
55+
"%prog [options] MORPHFILE TARGETFILE",
56+
"Manipulate and compare functions.",
5757
"Use --help for help.",
5858
]
5959
),
@@ -82,10 +82,10 @@ def custom_error(self, msg):
8282
dest="slocation",
8383
help=(
8484
"Save the manipulated function to a file named NAME. "
85-
"Use '-' for stdout.\n"
85+
"Use '-' for stdout. "
8686
"When --multiple-<targets/morphs> is enabled, "
8787
"save each manipulated function as a file in a directory "
88-
"named NAME;\n"
88+
"named NAME. "
8989
"you can specify names for each saved function file using "
9090
"--save-names-file."
9191
),
@@ -96,8 +96,8 @@ def custom_error(self, msg):
9696
dest="get_diff",
9797
action="store_true",
9898
help=(
99-
"Save the difference curve rather than the manipulated function.\n"
100-
"This is computed as manipulated function minus target function.\n"
99+
"Save the difference curve rather than the manipulated function. "
100+
"This is computed as manipulated function minus target function. "
101101
"The difference curve is computed on the interval shared by the "
102102
"grid of the objective and target function."
103103
),
@@ -141,21 +141,23 @@ def custom_error(self, msg):
141141
"--addpearson",
142142
action="store_true",
143143
dest="addpearson",
144-
help="""Maximize agreement in the Pearson function as well as
145-
minimizing the residual.""",
144+
help=(
145+
"Maximize agreement in the Pearson function as well as "
146+
"minimizing the residual."
147+
),
146148
)
147149

148150
# Manipulations
149151
group = optparse.OptionGroup(
150152
parser,
151153
"Manipulations",
152154
(
153-
"These options select the manipulations that are to be applied to "
154-
"the PDF from FILE1. "
155+
"These options select the manipulations that are to be applied "
156+
"to the function from MORPHFILE. "
155157
"The passed values will be refined unless specifically "
156158
"excluded with the -a or -x options. "
157-
"If no option is specified, the PDFs from FILE1 and FILE2 will "
158-
"be plotted without any manipulations."
159+
"If no option is specified, the functions from MORPHFILE and "
160+
"TARGETFILE will be plotted without any manipulations."
159161
),
160162
)
161163
parser.add_option_group(group)
@@ -237,20 +239,30 @@ def custom_error(self, msg):
237239
"--slope",
238240
type="float",
239241
dest="baselineslope",
240-
help="""Slope of the baseline. This is used with the option --smear-pdf
241-
to convert from the PDF to RDF. It will be estimated if not provided.""",
242+
help=(
243+
"Slope of the baseline. "
244+
"For a bulk material with scale factor 1, "
245+
"this will have value -4\u03C0 times the atomic density. "
246+
"Otherwise, you can estimate it by dividing the y "
247+
"position from the x position "
248+
"of the base of the first peak. "
249+
"This is used with the option "
250+
"--smear-pdf to convert from the PDF to RDF. "
251+
"It will be estimated as a number near"
252+
"-0.5 if not provided. "
253+
),
242254
)
243255
group.add_option(
244256
"--hshift",
245257
type="float",
246258
metavar="HSHIFT",
247-
help="Shift the PDF horizontally by HSHIFT to the right.",
259+
help="Shift the function horizontally by HSHIFT to the right.",
248260
)
249261
group.add_option(
250262
"--vshift",
251263
type="float",
252264
metavar="VSHIFT",
253-
help="Shift the PDF vertically by VSHIFT upward.",
265+
help="Shift the function vertically by VSHIFT upward.",
254266
)
255267
group.add_option(
256268
"--qdamp",
@@ -308,9 +320,9 @@ def custom_error(self, msg):
308320
parser,
309321
"Plot Options",
310322
(
311-
"These options control plotting. The manipulated and target PDFs "
312-
"will be plotted against each other with a difference curve "
313-
"below. "
323+
"These options control plotting. The manipulated and target"
324+
"functions will be plotted against each other with a difference "
325+
"curve below. "
314326
"When --multiple-<targets/morphs> is enabled, the value of a "
315327
"parameter (specified by --plot-parameter) will be plotted "
316328
"instead."
@@ -330,7 +342,7 @@ def custom_error(self, msg):
330342
dest="mlabel",
331343
help=(
332344
"Set label for morphed data to MLABEL on plot. "
333-
"Default label is FILE1."
345+
"Default label is MORPHFILE."
334346
),
335347
)
336348
group.add_option(
@@ -339,7 +351,7 @@ def custom_error(self, msg):
339351
dest="tlabel",
340352
help=(
341353
"Set label for target data to TLABEL on plot. "
342-
"Default label is FILE2."
354+
"Default label is TARGETFILE."
343355
),
344356
)
345357
group.add_option(
@@ -355,12 +367,12 @@ def custom_error(self, msg):
355367
group.add_option(
356368
"--maglim",
357369
type="float",
358-
help="Magnify plot curves beyond r=MAGLIM by MAG.",
370+
help="Magnify plot curves beyond x=MAGLIM by MAG.",
359371
)
360372
group.add_option(
361373
"--mag",
362374
type="float",
363-
help="Magnify plot curves beyond r=MAGLIM by MAG.",
375+
help="Magnify plot curves beyond x=MAGLIM by MAG.",
364376
)
365377
group.add_option(
366378
"--lwidth", type="float", help="Line thickness of plotted curves."
@@ -371,8 +383,9 @@ def custom_error(self, msg):
371383
parser,
372384
"Multiple Morphs",
373385
(
374-
"This program can morph a PDF against multiple targets in one "
375-
"command. See -s and Plot Options for how saving and plotting "
386+
"This program can morph a function against multiple targets in"
387+
" one command. "
388+
"See -s and Plot Options for how saving and plotting "
376389
"functionality changes when performing multiple morphs."
377390
),
378391
)
@@ -382,33 +395,51 @@ def custom_error(self, msg):
382395
dest="multiple_morphs",
383396
action="store_true",
384397
help=(
385-
f"Changes usage to '{prog_short} [options] FILE DIRECTORY'. "
386-
f"FILE will be morphed with each file in DIRECTORY as target. "
387-
f"Files in DIRECTORY are sorted by alphabetical order unless a "
388-
f"field is specified by --sort-by."
398+
f"Usage: '{prog_short} --multiple-morphs [options] DIRECTORY "
399+
f"TARGET'. "
400+
f"Morphs every file in DIRECTORY to the a single TARGET file. "
401+
f"Paths for DIRECTORY and TARGET are relative to the current "
402+
f"working directory. "
403+
"By default, the Rw for each morph is plotted, where the x-axis "
404+
"is sorted alphanumerically by filename of the file being "
405+
"morphed. "
406+
"Use --sort-by option to change the x-axis order. "
407+
"Use --plot-parameter to modify the parameter plotted on the "
408+
"y-axis."
389409
),
390410
)
391411
group.add_option(
392412
"--multiple-targets",
393413
dest="multiple_targets",
394414
action="store_true",
395415
help=(
396-
f"Changes usage to '{prog_short} [options] DIRECTORY FILE'. "
397-
f"Each file in DIRECTORY will be morphed with FILE as target. "
398-
f"Files in DIRECTORY are sorted by alphabetical order unless a "
399-
f"field is specified by --sort-by."
416+
f"Usage: '{prog_short} --multiple-targets [options] MORPH "
417+
f"DIRECTORY'. "
418+
f"Morphs the MORPH file to every file in DIRECTORY. "
419+
f"Paths for MORPH and DIRECTORY are relative to the current "
420+
f"working directory. "
421+
"By default, the Rw for each morph is plotted, where the x-axis "
422+
"is sorted alphanumerically by filename of the file being "
423+
"morphed. "
424+
"Use --sort-by option to change the x-axis order. "
425+
"Use --plot-parameter to modify the parameter plotted on the "
426+
"y-axis."
400427
),
401428
)
402429
group.add_option(
403430
"--sort-by",
404431
metavar="FIELD",
405432
dest="field",
406433
help=(
407-
"Used with --multiple-<targets/morphs> to sort files in DIRECTORY "
408-
"by FIELD. "
409-
"If the FIELD being used has a numerical value, sort from lowest "
410-
"to highest. Otherwise, sort in ASCII sort order. FIELD must be "
411-
"included in the header of all the PDF files."
434+
"Used with --multiple-<targets/morphs> to sort files in "
435+
"DIRECTORY by FIELD. "
436+
"If the FIELD being used has a numerical value, sort from "
437+
"lowest to highest unless --reverse is enabled. "
438+
"Otherwise, sort in ASCII sort order. "
439+
"The program will look for the FIELD (case insensitive) in the "
440+
"header of each of the files in DIRECTORY. "
441+
"If plotting is enabled, the x-axis of the plot will be the "
442+
"field."
412443
),
413444
)
414445
group.add_option(
@@ -421,22 +452,26 @@ def custom_error(self, msg):
421452
"--serial-file",
422453
metavar="SERIALFILE",
423454
dest="serfile",
424-
help="""Look for FIELD in a serial file instead.
425-
Must specify name of serial file SERIALFILE.""",
455+
help=(
456+
"Look for FIELD in a serialization file (e.g. .json) instead. "
457+
"Must specify name of serial file SERIALFILE."
458+
),
426459
)
427460
group.add_option(
428461
"--save-names-file",
429462
metavar="NAMESFILE",
430463
dest="snamesfile",
431464
help=(
432465
"Used when both -s and --multiple-<targets/morphs> are enabled. "
433-
"Specify names for each manipulated PDF when saving (see -s) "
434-
"using a serial file NAMESFILE. The format of NAMESFILE should be "
435-
"as follows: each target PDF is an entry in NAMESFILE. For each "
436-
"entry, there should be a key {__save_morph_as__} whose value "
437-
"specifies the name to save the manipulated function as."
438-
"An example .json serial file is included in the tutorial "
439-
"directory on the package GitHub repository."
466+
"Specify names for each manipulated function when saving "
467+
"(see -s) using a serial file NAMESFILE. "
468+
"The format of NAMESFILE should be as follows: "
469+
"each target function is an entry in NAMESFILE. "
470+
"For each entry, there should be a key {__save_morph_as__} "
471+
"whose value specifies the name to save the manipulated "
472+
"function as."
473+
"An example .json serialization file is included in the "
474+
"tutorial directory on the package GitHub repository."
440475
),
441476
)
442477
group.add_option(
@@ -472,10 +507,11 @@ def single_morph(
472507
parser, opts, pargs, stdout_flag=True, python_wrap=False, pymorphs=None
473508
):
474509
if len(pargs) < 2:
475-
parser.error("You must supply FILE1 and FILE2.")
510+
parser.error("You must supply MORPHFILE and TARGETFILE.")
476511
elif len(pargs) > 2 and not python_wrap:
477512
parser.error(
478-
"Too many arguments. Make sure you only supply FILE1 and FILE2."
513+
"Too many arguments. Make sure you only supply "
514+
"MORPHFILE and TARGETFILE."
479515
)
480516
elif not (len(pargs) == 2 or len(pargs) == 6) and python_wrap:
481517
parser.error("Python wrapper error.")
@@ -837,7 +873,7 @@ def multiple_targets(parser, opts, pargs, stdout_flag=True, python_wrap=False):
837873
# applied
838874
if len(pargs) < 2:
839875
parser.custom_error(
840-
"You must supply FILE and DIRECTORY. "
876+
"You must supply a FILE and DIRECTORY. "
841877
"See --multiple-targets under --help for usage."
842878
)
843879
elif len(pargs) > 2:
@@ -896,7 +932,7 @@ def multiple_targets(parser, opts, pargs, stdout_flag=True, python_wrap=False):
896932
)
897933
else:
898934
parser.custom_error(
899-
"The requested field is missing from a PDF file header."
935+
"The requested field is missing from a file header."
900936
)
901937
else:
902938
# Default is alphabetical sort
@@ -911,7 +947,7 @@ def multiple_targets(parser, opts, pargs, stdout_flag=True, python_wrap=False):
911947
save_names_file = (
912948
opts.snamesfile
913949
) # User-given serialfile with names for each morph
914-
save_morphs_here = None # Subdirectory for saving morphed PDFs
950+
save_morphs_here = None # Subdirectory for saving morphed functions
915951
save_names = {} # Dictionary of names to save each morph as
916952
if save_directory is not None:
917953
try:
@@ -1020,7 +1056,7 @@ def multiple_morphs(parser, opts, pargs, stdout_flag=True, python_wrap=False):
10201056
# applied
10211057
if len(pargs) < 2:
10221058
parser.custom_error(
1023-
"You must supply DIRECTORY and FILE. "
1059+
"You must supply a DIRECTORY and FILE. "
10241060
"See --multiple-morphs under --help for usage."
10251061
)
10261062
elif len(pargs) > 2:

tests/test_morphapp.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,18 +113,18 @@ def test_parser_systemexits(self, capsys, setup_parser):
113113
with pytest.raises(SystemExit):
114114
single_morph(self.parser, opts, pargs, stdout_flag=False)
115115
_, err = capsys.readouterr()
116-
assert "You must supply FILE1 and FILE2." in err
116+
assert "You must supply MORPHFILE and TARGETFILE." in err
117117
with pytest.raises(SystemExit):
118118
multiple_targets(self.parser, opts, pargs, stdout_flag=False)
119119
_, err = capsys.readouterr()
120-
assert "You must supply FILE and DIRECTORY." in err
120+
assert "You must supply a FILE and DIRECTORY." in err
121121
(opts, pargs) = self.parser.parse_args(["too", "many", "files"])
122122
with pytest.raises(SystemExit):
123123
single_morph(self.parser, opts, pargs, stdout_flag=False)
124124
_, err = capsys.readouterr()
125125
assert (
126-
"Too many arguments. Make sure you only supply FILE1 and FILE2."
127-
in err
126+
"Too many arguments. Make sure you only supply MORPHFILE and "
127+
"TARGETFILE." in err
128128
)
129129
with pytest.raises(SystemExit):
130130
multiple_targets(self.parser, opts, pargs, stdout_flag=False)
@@ -186,7 +186,7 @@ def test_parser_systemexits(self, capsys, setup_parser):
186186
with pytest.raises(SystemExit):
187187
multiple_targets(self.parser, opts, pargs, stdout_flag=False)
188188
_, err = capsys.readouterr()
189-
assert "The requested field is missing from a PDF file header." in err
189+
assert "The requested field is missing from a file header." in err
190190
(opts, pargs) = self.parser.parse_args(
191191
[
192192
f"{nickel_PDF}",

0 commit comments

Comments
 (0)