Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/source/morphpy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,11 @@ verbose: bool
Print additional header details to saved files. These include details about the morph
inputs and outputs.
xmin: float
Minimum r-value (abscissa) to use for function comparisons.
Minimum x-value (abscissa) to use for function comparisons.
xmax: float
Maximum r-value (abscissa) to use for function comparisons.
Maximum x-value (abscissa) to use for function comparisons.
tolerance: float
Specify least squares refiner tolerance when optimizing for morph parameters. Default: 10e-8.
Specify least squares refiner tolerance when optimizing for morph parameters. Default: 1e-8.
pearson: bool
The refiner instead maximizes agreement in the Pearson function
(default behavior is to minimize the residual).
Expand Down
23 changes: 23 additions & 0 deletions news/docstring.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
**Added:**

* <news item>

**Changed:**

* Docstrings updated for better clarity
Copy link
Contributor

Choose a reason for hiding this comment

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

this is a fix not a change. Changes refer to changes in user-functionality


**Deprecated:**

* <news item>

**Removed:**

* <news item>

**Fixed:**

* <news item>

**Security:**

* <news item>
124 changes: 76 additions & 48 deletions src/diffpy/morph/morphapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ def custom_error(self, msg):
parser = CustomParser(
usage="\n".join(
[
"%prog [options] FILE1 FILE2",
"Manipulate and compare PDFs.",
"%prog [options] MORPHFILE TARGETFILE",
"Manipulate and compare functions.",
"Use --help for help.",
]
),
Expand Down Expand Up @@ -82,10 +82,10 @@ def custom_error(self, msg):
dest="slocation",
help=(
"Save the manipulated function to a file named NAME. "
"Use '-' for stdout.\n"
"Use '-' for stdout. "
"When --multiple-<targets/morphs> is enabled, "
"save each manipulated function as a file in a directory "
"named NAME;\n"
"named NAME. "
"you can specify names for each saved function file using "
"--save-names-file."
),
Expand All @@ -96,8 +96,8 @@ def custom_error(self, msg):
dest="get_diff",
action="store_true",
help=(
"Save the difference curve rather than the manipulated function.\n"
"This is computed as manipulated function minus target function.\n"
"Save the difference curve rather than the manipulated function. "
"This is computed as manipulated function minus target function. "
"The difference curve is computed on the interval shared by the "
"grid of the objective and target function."
),
Expand Down Expand Up @@ -141,21 +141,23 @@ def custom_error(self, msg):
"--addpearson",
action="store_true",
dest="addpearson",
help="""Maximize agreement in the Pearson function as well as
minimizing the residual.""",
help=(
"Maximize agreement in the Pearson function as well as "
"minimizing the residual."
),
)

# Manipulations
group = optparse.OptionGroup(
parser,
"Manipulations",
(
"These options select the manipulations that are to be applied to "
"the PDF from FILE1. "
"These options select the manipulations that are to be applied "
"to the function from MORPHFILE. "
"The passed values will be refined unless specifically "
"excluded with the -a or -x options. "
"If no option is specified, the PDFs from FILE1 and FILE2 will "
"be plotted without any manipulations."
"If no option is specified, the functions from MORPHFILE and "
"TARGETFILE will be plotted without any manipulations."
),
)
parser.add_option_group(group)
Expand Down Expand Up @@ -237,8 +239,11 @@ def custom_error(self, msg):
"--slope",
type="float",
dest="baselineslope",
help="""Slope of the baseline. This is used with the option --smear-pdf
to convert from the PDF to RDF. It will be estimated if not provided.""",
help=(
"Slope of the baseline. This is used with the option "
"--smear-pdf to convert from the PDF to RDF. "
"It will be estimated if not provided."
),
)
group.add_option(
"--hshift",
Expand Down Expand Up @@ -308,9 +313,9 @@ def custom_error(self, msg):
parser,
"Plot Options",
(
"These options control plotting. The manipulated and target PDFs "
"will be plotted against each other with a difference curve "
"below. "
"These options control plotting. The manipulated and target"
"functions will be plotted against each other with a difference "
"curve below. "
"When --multiple-<targets/morphs> is enabled, the value of a "
"parameter (specified by --plot-parameter) will be plotted "
"instead."
Expand All @@ -330,7 +335,7 @@ def custom_error(self, msg):
dest="mlabel",
help=(
"Set label for morphed data to MLABEL on plot. "
"Default label is FILE1."
"Default label is MORPHFILE."
),
)
group.add_option(
Expand All @@ -339,7 +344,7 @@ def custom_error(self, msg):
dest="tlabel",
help=(
"Set label for target data to TLABEL on plot. "
"Default label is FILE2."
"Default label is TARGETFILE."
),
)
group.add_option(
Expand All @@ -355,12 +360,12 @@ def custom_error(self, msg):
group.add_option(
"--maglim",
type="float",
help="Magnify plot curves beyond r=MAGLIM by MAG.",
help="Magnify plot curves beyond x=MAGLIM by MAG.",
)
group.add_option(
"--mag",
type="float",
help="Magnify plot curves beyond r=MAGLIM by MAG.",
help="Magnify plot curves beyond x=MAGLIM by MAG.",
)
group.add_option(
"--lwidth", type="float", help="Line thickness of plotted curves."
Expand All @@ -371,8 +376,9 @@ def custom_error(self, msg):
parser,
"Multiple Morphs",
(
"This program can morph a PDF against multiple targets in one "
"command. See -s and Plot Options for how saving and plotting "
"This program can morph a function against multiple targets in"
" one command. "
"See -s and Plot Options for how saving and plotting "
"functionality changes when performing multiple morphs."
),
)
Expand All @@ -382,33 +388,51 @@ def custom_error(self, msg):
dest="multiple_morphs",
action="store_true",
help=(
f"Changes usage to '{prog_short} [options] FILE DIRECTORY'. "
f"FILE will be morphed with each file in DIRECTORY as target. "
f"Files in DIRECTORY are sorted by alphabetical order unless a "
f"field is specified by --sort-by."
f"Usage: '{prog_short} --multiple-morphs [options] DIRECTORY "
f"TARGET'. "
f"Morphs every file in DIRECTORY to the a single TARGET file. "
f"Paths for DIRECTORY and TARGET are relative to the current "
f"working directory. "
"By default, the Rw for each morph is plotted, where the x-axis "
"is sorted alphanumerically by filename of the file being "
"morphed. "
"Use --sort-by option to change the x-axis order. "
"Use --plot-parameter to modify the parameter plotted on the "
"y-axis."
),
)
group.add_option(
"--multiple-targets",
dest="multiple_targets",
action="store_true",
help=(
f"Changes usage to '{prog_short} [options] DIRECTORY FILE'. "
f"Each file in DIRECTORY will be morphed with FILE as target. "
f"Files in DIRECTORY are sorted by alphabetical order unless a "
f"field is specified by --sort-by."
f"Usage: '{prog_short} --multiple-targets [options] MORPH "
f"DIRECTORY'. "
f"Morphs the MORPH file to every file in DIRECTORY. "
f"Paths for MORPH and DIRECTORY are relative to the current "
f"working directory. "
"By default, the Rw for each morph is plotted, where the x-axis "
"is sorted alphanumerically by filename of the file being "
"morphed. "
"Use --sort-by option to change the x-axis order. "
"Use --plot-parameter to modify the parameter plotted on the "
"y-axis."
),
)
group.add_option(
"--sort-by",
metavar="FIELD",
dest="field",
help=(
"Used with --multiple-<targets/morphs> to sort files in DIRECTORY "
"by FIELD. "
"If the FIELD being used has a numerical value, sort from lowest "
"to highest. Otherwise, sort in ASCII sort order. FIELD must be "
"included in the header of all the PDF files."
"Used with --multiple-<targets/morphs> to sort files in "
"DIRECTORY by FIELD. "
"If the FIELD being used has a numerical value, sort from "
"lowest to highest unless --reverse is enabled. "
"Otherwise, sort in ASCII sort order. "
"The program will look for the FIELD (case insensitive) in the "
"header of each of the files in DIRECTORY. "
"If plotting is enabled, the x-axis of the plot will be the "
"field."
),
)
group.add_option(
Expand All @@ -421,8 +445,10 @@ def custom_error(self, msg):
"--serial-file",
metavar="SERIALFILE",
dest="serfile",
help="""Look for FIELD in a serial file instead.
Must specify name of serial file SERIALFILE.""",
help=(
"Look for FIELD in a serial file instead. "
Copy link
Contributor

Choose a reason for hiding this comment

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

What is a "serial file"? I think we need some more user-friendly text to help with understanding here.

"Must specify name of serial file SERIALFILE."
),
)
group.add_option(
"--save-names-file",
Expand All @@ -431,10 +457,11 @@ def custom_error(self, msg):
help=(
"Used when both -s and --multiple-<targets/morphs> are enabled. "
"Specify names for each manipulated PDF when saving (see -s) "
"using a serial file NAMESFILE. The format of NAMESFILE should be "
"as follows: each target PDF is an entry in NAMESFILE. For each "
"entry, there should be a key {__save_morph_as__} whose value "
"specifies the name to save the manipulated function as."
"using a serial file NAMESFILE. The format of NAMESFILE should "
"be as follows: each target PDF is an entry in NAMESFILE. "
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we want PDF out here? function instead?

"For each entry, there should be a key {__save_morph_as__} "
"whose value specifies the name to save the manipulated "
"function as."
"An example .json serial file is included in the tutorial "
"directory on the package GitHub repository."
),
Expand Down Expand Up @@ -472,10 +499,11 @@ def single_morph(
parser, opts, pargs, stdout_flag=True, python_wrap=False, pymorphs=None
):
if len(pargs) < 2:
parser.error("You must supply FILE1 and FILE2.")
parser.error("You must supply MORPHFILE and TARGETFILE.")
elif len(pargs) > 2 and not python_wrap:
parser.error(
"Too many arguments. Make sure you only supply FILE1 and FILE2."
"Too many arguments. Make sure you only supply "
"MORPHFILE and TARGETFILE."
)
elif not (len(pargs) == 2 or len(pargs) == 6) and python_wrap:
parser.error("Python wrapper error.")
Expand Down Expand Up @@ -836,7 +864,7 @@ def multiple_targets(parser, opts, pargs, stdout_flag=True, python_wrap=False):
# applied
if len(pargs) < 2:
parser.custom_error(
"You must supply FILE and DIRECTORY. "
"You must supply a FILE and DIRECTORY. "
"See --multiple-targets under --help for usage."
)
elif len(pargs) > 2:
Expand Down Expand Up @@ -895,7 +923,7 @@ def multiple_targets(parser, opts, pargs, stdout_flag=True, python_wrap=False):
)
else:
parser.custom_error(
"The requested field is missing from a PDF file header."
"The requested field is missing from a file header."
)
else:
# Default is alphabetical sort
Expand All @@ -910,7 +938,7 @@ def multiple_targets(parser, opts, pargs, stdout_flag=True, python_wrap=False):
save_names_file = (
opts.snamesfile
) # User-given serialfile with names for each morph
save_morphs_here = None # Subdirectory for saving morphed PDFs
save_morphs_here = None # Subdirectory for saving morphed functions
save_names = {} # Dictionary of names to save each morph as
if save_directory is not None:
try:
Expand Down Expand Up @@ -1019,7 +1047,7 @@ def multiple_morphs(parser, opts, pargs, stdout_flag=True, python_wrap=False):
# applied
if len(pargs) < 2:
parser.custom_error(
"You must supply DIRECTORY and FILE. "
"You must supply a DIRECTORY and FILE. "
"See --multiple-morphs under --help for usage."
)
elif len(pargs) > 2:
Expand Down
10 changes: 5 additions & 5 deletions tests/test_morphapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,18 +113,18 @@ def test_parser_systemexits(self, capsys, setup_parser):
with pytest.raises(SystemExit):
single_morph(self.parser, opts, pargs, stdout_flag=False)
_, err = capsys.readouterr()
assert "You must supply FILE1 and FILE2." in err
assert "You must supply MORPHFILE and TARGETFILE." in err
with pytest.raises(SystemExit):
multiple_targets(self.parser, opts, pargs, stdout_flag=False)
_, err = capsys.readouterr()
assert "You must supply FILE and DIRECTORY." in err
assert "You must supply a FILE and DIRECTORY." in err
(opts, pargs) = self.parser.parse_args(["too", "many", "files"])
with pytest.raises(SystemExit):
single_morph(self.parser, opts, pargs, stdout_flag=False)
_, err = capsys.readouterr()
assert (
"Too many arguments. Make sure you only supply FILE1 and FILE2."
in err
"Too many arguments. Make sure you only supply MORPHFILE and "
"TARGETFILE." in err
)
with pytest.raises(SystemExit):
multiple_targets(self.parser, opts, pargs, stdout_flag=False)
Expand Down Expand Up @@ -186,7 +186,7 @@ def test_parser_systemexits(self, capsys, setup_parser):
with pytest.raises(SystemExit):
multiple_targets(self.parser, opts, pargs, stdout_flag=False)
_, err = capsys.readouterr()
assert "The requested field is missing from a PDF file header." in err
assert "The requested field is missing from a file header." in err
(opts, pargs) = self.parser.parse_args(
[
f"{nickel_PDF}",
Expand Down
Loading