diff --git a/doc/manual/pdfmorph.pdf b/doc/manual/pdfmorph.pdf index 06e470c..779e49f 100644 Binary files a/doc/manual/pdfmorph.pdf and b/doc/manual/pdfmorph.pdf differ diff --git a/doc/manual/pdfmorph.texinfo b/doc/manual/pdfmorph.texinfo index 7239202..9620914 100644 --- a/doc/manual/pdfmorph.texinfo +++ b/doc/manual/pdfmorph.texinfo @@ -462,10 +462,10 @@ Long Yang. @item Let us start by getting the @math{R_W} of @code{SrFe2As2_150K.gr} compared to the other, higher-temperature PDFs in the directory. Run @example -pdfmorph SrFe2As2_150K.gr . --multiple +pdfmorph SrFe2As2_150K.gr . --multiple-targets @end example @itemize -@item The @code{--multiple} tag tells @code{PDFmorph} to compare the morphed file +@item The @code{--multiple-targets} tag tells @code{PDFmorph} to compare the morphed file @code{SrFe2As2_150K.gr} against all PDFs in a directory. The directory we have supplied is @code{.}, which is shorthand for the current working directory. In our case, this is the @code{morphMultiple} directory. @@ -489,7 +489,7 @@ included are temperature, wavelength, and composition.} @end float @item By running @example -pdfmorph SrFe2As2_150K.gr . --multiple --sort-by=temperature +pdfmorph SrFe2As2_150K.gr . --multiple-targets --sort-by=temperature @end example we can sort the plotted @math{R_W} values by the temperature parameter included within each file. @itemize @@ -506,7 +506,7 @@ instead of @code{temperature}. a phase change. To be more certain, let us apply morphs to take into account isotropic expansion and differences in incident flux (stretching and scaling). @example -pdfmorph SrFe2As2_150K.gr . --scale=1 --stretch=0 --multiple \ +pdfmorph SrFe2As2_150K.gr . --scale=1 --stretch=0 --multiple-targets \ --sort-by=temperature @end example The change in @math{R_W} has become more pronounced. @@ -517,7 +517,7 @@ not significantly change the @math{R_W} values in this example. @item We can also change what is being plotted in the ordinate using @code{--plot-parameter}. In our case, it is useful to look at the @code{stretch} factor @example -pdfmorph SrFe2As2_150K.gr . --scale=1 --stretch=0 --multiple \ +pdfmorph SrFe2As2_150K.gr . --scale=1 --stretch=0 --multiple-targets \ --sort-by=temperature --plot-parameter=stretch @end example We can see that the stretch factor generally increases, but from @math{192K} to @math{198K}, there is no increase. @@ -533,7 +533,7 @@ can be done with @url{https://www.diffpy.org/products/pdfgui, PDFgui}. @end float @item Finally, let us save all the morphed PDFs into a directory named @code{savedMorphs}. @example -pdfmorph SrFe2As2_150K.gr . --scale=1 --stretch=0 --multiple \ +pdfmorph SrFe2As2_150K.gr . --scale=1 --stretch=0 --multiple-targets \ --sort-by=temperature --plot-parameter=stretch \ --save=savedMorphs @end example @@ -877,8 +877,8 @@ the residual with the target PDF. @noindent @code{-s NAME, --save=NAME} @* @indent Save the morphed PDF into a file named @code{NAME}. You can use @code{-} to save to @code{stdout} instead. -When you have the @code{--multiple} tag enabled, multiple morphed PDFs are -generated. Using this command with the @code{--multiple} tag will save all +When you have the @code{--multiple-targets} tag enabled, multiple morphed PDFs are +generated. Using this command with the @code{--multiple-targets} tag will save all these morphs into a directory named @code{NAME} as well as a @code{.txt} file summary of refined morph parameters (if applicable) and @math{R_W} for each morph done. To specify names for each saved PDF file, use the @@ -981,7 +981,7 @@ function of a sphere with radius @code{IPRADIUS}. @noindent @titlefont{@b{Plot options}} These options control plotting. The morphed and target PDFs will be plotted against each other with a -difference curve shown below. The following changes occur when @code{--multiple} is enabled. +difference curve shown below. The following changes occur when @code{--multiple-targets} is enabled. (1) The @math{R_W} for each morphed PDF compared to the target will be plotted unless another parameter is specified by @code{--plot-parameter}. (2) The plot will be a bar chart where the abscissa names are the file names of the target PDFs unless otherwise specified by @@ -1020,11 +1020,11 @@ be useful as PDF amplitude can get very small for large @math{r}. No magnificati @noindent @titlefont{@b{Multiple morphs}} -@code{PDFmorph} allows one to morph one PDF against multiple different targets when @code{--multiple} +@code{PDFmorph} allows one to morph one PDF against multiple different targets when @code{--multiple-targets} is enabled. See @code{-s} and the description under "Plot options" for how saving and plotting -change when @code{--multiple} is enabled. +change when @code{--multiple-targets} is enabled. -@noindent @code{--multiple} +@noindent @code{--multiple-targets} @* @indent Changes usage of @code{PDFmorph} to @example pdfmorph @@ -1034,7 +1034,7 @@ in the directory @code{TARGET_DIRECTORY} as the target. Files in @code{TARGET_DI be sorted in ASCII sort order order unless a sorting parameter is specified by @code{sort-by}. @noindent @code{--sort-by=FIELD} -@* @indent Used with @code{--multiple}. Sort the files in @code{TARGET_DIRECTORY} by some parameter +@* @indent Used with @code{--multiple-targets}. Sort the files in @code{TARGET_DIRECTORY} by some parameter named @code{FIELD}. Parameters can be specified within each target PDF file by lines of the form @code{ = } in the header (anywhere above the @math{r} versus @math{G(r)} data table). @code{PDFmorph} will attempt to find a parameter named @code{FIELD} using a @@ -1042,17 +1042,17 @@ case-insensitive search. Numerical @code{PARAM_VALUE} will be sorted in ascendin non-numerical ones will be sorted in ASCII sort order. @noindent @code{--reverse} -@* @indent Used with @code{--multiple}. Sort the files in @code{TARGET_DIRECTORY} in reverse +@* @indent Used with @code{--multiple-targets}. Sort the files in @code{TARGET_DIRECTORY} in reverse ASCII sort order. If a parameter is given by @code{--sort-by}, reverse the order given by @code{--sort-by}. @noindent @code{--serial-file=SERIALFILE} -@* @indent Used with @code{--multiple} and @code{--sort-by}. Look for @code{FIELD} in a serial +@* @indent Used with @code{--multiple-targets} and @code{--sort-by}. Look for @code{FIELD} in a serial file named @code{SERIALFILE} instead. Only serial file types supported by @url{https://www.diffpy.org/diffpy.utils, diffpy.utils} such as @code{.json} are allowed. @noindent @code{--save-names-file=NAMESFILE} -@* @indent Used with @code{--multiple} and @code{-s}. Specify names for each manipulated PDF when +@* @indent Used with @code{--multiple-targets} and @code{-s}. Specify names for each manipulated PDF when saving using a serial file named @code{NAMESFILE}. The format of @code{NAMESFILE} should be as follows: (1) Each target PDF file name is an entry in @code{NAMESFILE}. (2) For each entry, there should be a key @code{save_morph_as} whose value specified the name to save the manipulated @@ -1076,7 +1076,7 @@ PDF as. An example @code{.json} @code{NAMESFILE} is below. such as @code{.json} are allowed. @noindent @code{--plot-parameter=PLOTPARAM} -@* @indent Used with @code{--multiple} and when plotting is enabled. Choose a parameter @code{PLOTPARAM} +@* @indent Used with @code{--multiple-targets} and when plotting is enabled. Choose a parameter @code{PLOTPARAM} to plot for each morph. When not specified, the @math{R_W} values for each morphed PDF compared to the target PDFs will be plotted. This option is not case sensitive meaning @code{--plot-parameter=Scale} and @code{--plot-parameter=scale} will both cause the parameter @code{scale} to be plotted. diff --git a/doc/source/quickstart.rst b/doc/source/quickstart.rst index d893519..cd3c6d9 100644 --- a/doc/source/quickstart.rst +++ b/doc/source/quickstart.rst @@ -203,7 +203,7 @@ selected directory and plot resulting :math:`R_w` values from each morph. 2. Let us start by getting the Rw of ``SrFe2As2_150K.gr`` compared to all other files in the directory. Run :: - pdfmorph SrFe2As2_150K.gr . --multiple + pdfmorph SrFe2As2_150K.gr . --multiple-targets The multiple tag indicates we are comparing PDF file (first input) against all PDFs in a directory (second input). Our choice of file was ``SeFe2As2_150K.gr`` @@ -211,7 +211,7 @@ selected directory and plot resulting :math:`R_w` values from each morph. 3. After running this, we get chart of Rw values for each target file. However, this chart can be a bit confusing to interpret. To get a more understandable plot, run :: - pdfmorph SrFe2As2_150K.gr . --multiple --sort-by=temperature + pdfmorph SrFe2As2_150K.gr . --multiple-targets --sort-by=temperature This plots the Rw against the temperature parameter value provided at the top of each file. Parameters are entries of the form `` = `` and are located @@ -220,7 +220,7 @@ selected directory and plot resulting :math:`R_w` values from each morph. To confirm, let us now apply morphs onto ``SrFe2As2_150K.gr`` with all other files in ``morphMultiple`` as targets :: - pdfmorph --scale=1 --stretch=0 SrFe2As2_150K.gr . --multiple --sort-by=temperature + pdfmorph --scale=1 --stretch=0 SrFe2As2_150K.gr . --multiple-targets --sort-by=temperature Note that we are not applying a smear since it takes a long time to apply and does not significantly change the Rw values in this example. diff --git a/news/multiple_morphs.rst b/news/multiple_morphs.rst new file mode 100644 index 0000000..d05da82 --- /dev/null +++ b/news/multiple_morphs.rst @@ -0,0 +1,23 @@ +**Added:** + +* --multiple-morphs: morph multiple files against a single target + +**Changed:** + +* --multiple changed to --multiple-targets for clarity + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* diff --git a/pyproject.toml b/pyproject.toml index 1ad98a9..58e9bc7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,7 @@ maintainers = [ description = "Tools for manipulating and comparing PDF profiles" keywords = ['diffpy', 'pdf', 'data interpretation'] readme = "README.rst" -requires-python = ">=3.11, <3.14" +requires-python = ">=3.10, <3.14" classifiers = [ 'Development Status :: 5 - Production/Stable', 'Environment :: Console', @@ -25,6 +25,7 @@ classifiers = [ 'Operating System :: Microsoft :: Windows', 'Operating System :: POSIX', 'Operating System :: Unix', + 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12', 'Programming Language :: Python :: 3.13', diff --git a/src/diffpy/pdfmorph/pdfmorph_io.py b/src/diffpy/pdfmorph/pdfmorph_io.py index 81a96ec..c9b69d7 100644 --- a/src/diffpy/pdfmorph/pdfmorph_io.py +++ b/src/diffpy/pdfmorph/pdfmorph_io.py @@ -124,7 +124,7 @@ def create_morphs_directory(save_directory): return str(morphs_subdirectory.resolve()) -def get_multisave_names(target_list: list, save_names_file=None): +def get_multisave_names(target_list: list, save_names_file=None, mm=False): """Create or import a dictionary that specifies names to save morphs as. First attempt to import names from a specified file. If names for certain morphs not found, use default naming scheme: 'Morph_with_Target_.cgr'. @@ -134,9 +134,11 @@ def get_multisave_names(target_list: list, save_names_file=None): Parameters ---------- target_list: list - Target PDFs used for each morph. + Target (or Morph if mm enabled) PDFs used for each morph. save_names_file Name of file to import save names dictionary from (default None). + mm: bool + Rather than multiple targets, multiple morphs are being done. Returns ------- @@ -154,7 +156,12 @@ def get_multisave_names(target_list: list, save_names_file=None): # Apply default naming scheme to missing targets for target_file in target_list: if target_file.name not in save_names.keys(): - save_names.update({target_file.name: {__save_morph_as__: f"Morph_with_Target_{target_file.stem}.cgr"}}) + if not mm: + save_names.update( + {target_file.name: {__save_morph_as__: f"Morph_with_Target_{target_file.stem}.cgr"}} + ) + else: + save_names.update({target_file.name: {__save_morph_as__: f"Morph_of_{target_file.stem}.cgr"}}) return save_names @@ -169,6 +176,7 @@ def multiple_morph_output( target_directory=None, verbose=False, stdout_flag=False, + mm=False, ): """Helper function for printing details about a series of multiple morphs. Handles both printing to terminal and printing to a file. @@ -196,6 +204,9 @@ def multiple_morph_output( Print additional summary details when True (default False). stdout_flag: bool Print to terminal when True (default False). + mm: bool + Multiple morphs done with a single target rather than multiple targets for a single morphed file. + Swaps morph and target in the code. """ # Input parameters used for every morph @@ -207,7 +218,10 @@ def multiple_morph_output( if verbose: # Output for every morph (information repeated in a succinct table below) for target in morph_results.keys(): - output = f"\n# Target: {target}\n" + if not mm: + output = f"\n# Target: {target}\n" + else: + output = f"\n# Morph: {target}\n" output += "# Optimized morphing parameters:\n" output += "\n".join( f"# {param} = {morph_results[target][param]:.6f}" for param in morph_results[target] @@ -218,7 +232,10 @@ def multiple_morph_output( tabulated_results = tabulate_results(morph_results) # Table labels - labels = "\n# Labels: [Target]" + if not mm: + labels = "\n# Labels: [Target]" + else: + labels = "\n# Labels: [Morph]" if field is not None: labels += f" [{field}]" for param in tabulated_results.keys(): @@ -247,8 +264,12 @@ def multiple_morph_output( target_path_name = str(Path(target_directory).resolve()) header = "# Data generated by pdfmorph\n" - header += f"# from morphing {morph_path_name}\n" - header += f"# with target directory {target_path_name}" + if not mm: + header += f"# from morphing {morph_path_name}\n" + header += f"# with target directory {target_path_name}" + else: + header += f"# from morphing directory {target_path_name}\n" + header += f"# with target {morph_path_name}" reference_table = Path(save_directory).joinpath("Morph_Reference_Table.txt") with open(reference_table, "w") as reference: print(f"{header}\n{inputs}\n{verbose_outputs}{table}", file=reference) diff --git a/src/diffpy/pdfmorph/pdfmorphapp.py b/src/diffpy/pdfmorph/pdfmorphapp.py index 7f26ac0..041ddd5 100755 --- a/src/diffpy/pdfmorph/pdfmorphapp.py +++ b/src/diffpy/pdfmorph/pdfmorphapp.py @@ -69,7 +69,7 @@ def custom_error(self, msg): metavar="NAME", dest="slocation", help="""Save the manipulated PDF to a file named NAME. Use \'-\' for stdout. - When --multiple is enabled, save each manipulated PDF as a file in a directory named NAME; + When --multiple- is enabled, save each manipulated PDF as a file in a directory named NAME; you can specify names for each saved PDF file using --save-names-file.""", ) parser.add_option( @@ -186,7 +186,7 @@ def custom_error(self, msg): "Plot Options", """These options control plotting. The manipulated and target PDFs will be plotted against each other with a - difference curve below. When --multiple is enabled, the value of a parameter (specified by + difference curve below. When --multiple- is enabled, the value of a parameter (specified by --plot-parameter) will be plotted instead.""", ) parser.add_option_group(group) @@ -224,19 +224,28 @@ def custom_error(self, msg): ) parser.add_option_group(group) group.add_option( - "--multiple", - dest="multiple", + "--multiple-morphs", + dest="multiple_morphs", action="store_true", help=f"""Changes usage to \'{prog_short} [options] FILE DIRECTORY\'. FILE will be morphed with each file in DIRECTORY as target. Files in DIRECTORY are sorted by alphabetical order unless a field is + specified by --sort-by.""", + ) + group.add_option( + "--multiple-targets", + dest="multiple_targets", + action="store_true", + help=f"""Changes usage to \'{prog_short} [options] DIRECTORY FILE\'. Each file + in DIRECTORY will be morphed with FILE as target. + Files in DIRECTORY are sorted by alphabetical order unless a field is specified by --sort-by.""", ) group.add_option( "--sort-by", metavar="FIELD", dest="field", - help="""Used with --multiple to sort files in DIRECTORY by FIELD. + help="""Used with --multiple- 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.""", @@ -258,7 +267,7 @@ def custom_error(self, msg): "--save-names-file", metavar="NAMESFILE", dest="snamesfile", - help=f"""Used when both -s and --multiple are enabled. + help=f"""Used when both -s and --multiple- 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__} @@ -269,7 +278,7 @@ def custom_error(self, msg): "--plot-parameter", metavar="PLOTPARAM", dest="plotparam", - help="""Used when both plotting and --multiple are enabled. + help="""Used when both plotting and --multiple- are enabled. Choose a PLOTPARAM to plot for each morph (i.e. adding --plot-parameter=Pearson means the program will display a plot of the Pearson correlation coefficient for each morph-target pair). PLOTPARAM is not case sensitive, so both Pearson and pearson indicate the same @@ -300,6 +309,11 @@ def single_morph(parser, opts, pargs, stdout_flag=True): x_morph, y_morph = getPDFFromFile(pargs[0]) x_target, y_target = getPDFFromFile(pargs[1]) + if y_morph is None: + parser.error(f"No data table found in file: {pargs[0]}.") + if y_target is None: + parser.error(f"No data table found in file: {pargs[1]}.") + # Get configuration values scale_in = "None" stretch_in = "None" @@ -471,10 +485,10 @@ def single_morph(parser, opts, pargs, stdout_flag=True): return morph_results -def multiple_morphs(parser, opts, pargs, stdout_flag=True): +def multiple_targets(parser, opts, pargs, stdout_flag=True): # Custom error messages since usage is distinct when --multiple tag is applied if len(pargs) < 2: - parser.custom_error("You must supply FILE and DIRECTORY. See --multiple under --help for usage.") + parser.custom_error("You must supply FILE and DIRECTORY. See --multiple-targets under --help for usage.") elif len(pargs) > 2: parser.custom_error("Too many arguments. You must only supply a FILE and a DIRECTORY.") @@ -615,6 +629,151 @@ def multiple_morphs(parser, opts, pargs, stdout_flag=True): return morph_results +def multiple_morphs(parser, opts, pargs, stdout_flag=True): + # Custom error messages since usage is distinct when --multiple tag is applied + if len(pargs) < 2: + parser.custom_error("You must supply DIRECTORY and FILE. See --multiple-morphs under --help for usage.") + elif len(pargs) > 2: + parser.custom_error("Too many arguments. You must only supply a DIRECTORY and FILE.") + + # Parse paths + target_file = Path(pargs[1]) + if not target_file.is_file(): + parser.custom_error(f"{target_file} is not a file. Go to --help for usage.") + morph_directory = Path(pargs[0]) + if not morph_directory.is_dir(): + parser.custom_error(f"{morph_directory} is not a directory. Go to --help for usage.") + + # Get list of files from morph directory + morph_list = list(morph_directory.iterdir()) + for morph in morph_list: + if morph.is_dir(): + morph_list.remove(morph) + + # Do not morph target_file against itself if it is in the same directory + if target_file in morph_list: + morph_list.remove(target_file) + + # Format field name for printing and plotting + field = None + if opts.field is not None: + field_words = opts.field.split() + field = "" + for word in field_words: + field += f"{word[0].upper()}{word[1:].lower()}" + field_list = None + + # Sort files in directory by some field + if field is not None: + try: + morph_list, field_list = tools.field_sort( + morph_list, field, opts.reverse, opts.serfile, get_field_values=True + ) + except KeyError: + if opts.serfile is not None: + parser.custom_error("The requested field was not found in the metadata file.") + else: + parser.custom_error("The requested field is missing from a PDF file header.") + else: + # Default is alphabetical sort + morph_list.sort(reverse=opts.reverse) + + # Disable single morph plotting + plot_opt = opts.plot + opts.plot = False + + # Set up saving + save_directory = opts.slocation # User-given directory for saves + save_names_file = opts.snamesfile # User-given serialfile with names for each morph + save_morphs_here = None # Subdirectory for saving morphed PDFs + save_names = {} # Dictionary of names to save each morph as + if save_directory is not None: + try: + save_morphs_here = io.create_morphs_directory(save_directory) + + # Could not create directory or find names to save morphs as + except (FileNotFoundError, RuntimeError): + save_fail_message = "\nUnable to create directory" + parser.custom_error(save_fail_message) + + try: + save_names = io.get_multisave_names(morph_list, save_names_file=save_names_file) + # Could not create directory or find names to save morphs as + except FileNotFoundError: + save_fail_message = "\nUnable to read from save names file" + parser.custom_error(save_fail_message) + + # Morph morph_file against all other files in target_directory + morph_results = {} + for morph_file in morph_list: + if morph_file.is_file: + # Set the save file destination to be a file within the SLOC directory + if save_directory is not None: + save_as = save_names[morph_file.name][__save_morph_as__] + opts.slocation = Path(save_morphs_here).joinpath(save_as) + # Perform a morph of morph_file against target_file + pargs = [morph_file, target_file] + morph_results.update( + { + morph_file.name: single_morph(parser, opts, pargs, stdout_flag=False), + } + ) + + morph_file_names = [] + for key in morph_results.keys(): + morph_file_names.append(key) + + morph_inputs = {"scale": opts.scale, "stretch": opts.stretch, "smear": opts.smear} + + try: + # Print summary of morphs to terminal and to file (if requested) + io.multiple_morph_output( + morph_inputs, + morph_results, + morph_file_names, + save_directory=save_directory, + morph_file=target_file, + target_directory=morph_directory, + field=field, + field_list=field_list, + verbose=opts.verbose, + stdout_flag=stdout_flag, + mm=True, + ) + except (FileNotFoundError, RuntimeError): + save_fail_message = "Unable to save summary to directory." + parser.custom_error(save_fail_message) + + # Plot the values of some parameter for each target if requested + if plot_opt: + plot_results = io.tabulate_results(morph_results) + # Default parameter is Rw + param_name = r"$R_w$" + param_list = plot_results["Rw"] + # Find parameter if specified + if opts.plotparam is not None: + param_name = opts.plotparam + param_list = tools.case_insensitive_dictionary_search(opts.plotparam, plot_results) + # Not an available parameter to plot or no values found for the parameter + if param_list is None: + parser.custom_error("Cannot find specified plot parameter. No plot shown.") + else: + try: + if field_list is not None: + pdfplot.plot_param(field_list, param_list, param_name, field) + else: + pdfplot.plot_param(morph_file_names, param_list, param_name) + # Can occur for non-refined plotting parameters + # i.e. --smear is not selected as an option, but smear is the plotting parameter + except ValueError: + parser.custom_error( + "The plot parameter is missing values for at least one morph and target pair. " + "No plot shown." + ) + + return morph_results + + def getPDFFromFile(fn): from diffpy.pdfmorph.tools import readPDF @@ -633,7 +792,9 @@ def getPDFFromFile(fn): def main(): parser = create_option_parser() (opts, pargs) = parser.parse_args() - if opts.multiple: + if opts.multiple_targets: + multiple_targets(parser, opts, pargs, stdout_flag=True) + elif opts.multiple_morphs: multiple_morphs(parser, opts, pargs, stdout_flag=True) else: single_morph(parser, opts, pargs, stdout_flag=True) diff --git a/tests/test_pdfmorphapp.py b/tests/test_pdfmorphapp.py index f035d06..62b84c8 100644 --- a/tests/test_pdfmorphapp.py +++ b/tests/test_pdfmorphapp.py @@ -4,7 +4,7 @@ import pytest -from diffpy.pdfmorph.pdfmorphapp import create_option_parser, multiple_morphs, single_morph +from diffpy.pdfmorph.pdfmorphapp import create_option_parser, multiple_targets, single_morph thisfile = locals().get("__file__", "file.py") tests_dir = Path(thisfile).parent.resolve() @@ -87,12 +87,12 @@ def test_parser_systemexits(self, setup_parser): with pytest.raises(SystemExit): single_morph(self.parser, opts, pargs, stdout_flag=False) with pytest.raises(SystemExit): - multiple_morphs(self.parser, opts, pargs, stdout_flag=False) + multiple_targets(self.parser, opts, pargs, stdout_flag=False) (opts, pargs) = self.parser.parse_args(["too", "many", "files"]) with pytest.raises(SystemExit): single_morph(self.parser, opts, pargs, stdout_flag=False) with pytest.raises(SystemExit): - multiple_morphs(self.parser, opts, pargs, stdout_flag=False) + multiple_targets(self.parser, opts, pargs, stdout_flag=False) # Make sure rmax greater than rmin (opts, pargs) = self.parser.parse_args([f"{nickel_PDF}", f"{nickel_PDF}", "--rmin", "10", "--rmax", "1"]) @@ -112,20 +112,20 @@ def test_parser_systemexits(self, setup_parser): with pytest.raises(SystemExit): single_morph(self.parser, opts, pargs, stdout_flag=False) with pytest.raises(SystemExit): - multiple_morphs(self.parser, opts, pargs, stdout_flag=False) + multiple_targets(self.parser, opts, pargs, stdout_flag=False) # Ensure first parg is a FILE and second parg is a DIRECTORY (opts, pargs) = self.parser.parse_args([f"{nickel_PDF}", f"{nickel_PDF}"]) with pytest.raises(SystemExit): - multiple_morphs(self.parser, opts, pargs, stdout_flag=False) + multiple_targets(self.parser, opts, pargs, stdout_flag=False) (opts, pargs) = self.parser.parse_args([f"{testsequence_dir}", f"{testsequence_dir}"]) with pytest.raises(SystemExit): - multiple_morphs(self.parser, opts, pargs, stdout_flag=False) + multiple_targets(self.parser, opts, pargs, stdout_flag=False) # Try sorting by non-existing field (opts, pargs) = self.parser.parse_args([f"{nickel_PDF}", f"{testsequence_dir}", "--sort-by", "fake_field"]) with pytest.raises(SystemExit): - multiple_morphs(self.parser, opts, pargs, stdout_flag=False) + multiple_targets(self.parser, opts, pargs, stdout_flag=False) (opts, pargs) = self.parser.parse_args( [ f"{nickel_PDF}", @@ -137,21 +137,21 @@ def test_parser_systemexits(self, setup_parser): ] ) with pytest.raises(SystemExit): - multiple_morphs(self.parser, opts, pargs, stdout_flag=False) + multiple_targets(self.parser, opts, pargs, stdout_flag=False) # Try plotting an unknown parameter (opts, pargs) = self.parser.parse_args( [f"{nickel_PDF}", f"{testsequence_dir}", "--plot-parameter", "unknown"] ) with pytest.raises(SystemExit): - multiple_morphs(self.parser, opts, pargs, stdout_flag=False) + multiple_targets(self.parser, opts, pargs, stdout_flag=False) # Try plotting an unrefined parameter (opts, pargs) = self.parser.parse_args( [f"{nickel_PDF}", f"{testsequence_dir}", "--plot-parameter", "stretch"] ) with pytest.raises(SystemExit): - multiple_morphs(self.parser, opts, pargs, stdout_flag=False) + multiple_targets(self.parser, opts, pargs, stdout_flag=False) def test_morphsequence(self, setup_morphsequence): # Parse arguments sorting by field @@ -164,12 +164,12 @@ def test_morphsequence(self, setup_morphsequence): morph_file = self.testfiles[0] for target_file in self.testfiles[1:]: pargs = [morph_file, target_file] - # store in same format of dictionary as multiple_morphs + # store in same format of dictionary as multiple_targets single_results.update({target_file.name: single_morph(self.parser, opts, pargs, stdout_flag=False)}) pargs = [morph_file, testsequence_dir] # Run a morph sequence - sequence_results = multiple_morphs(self.parser, opts, pargs, stdout_flag=False) + sequence_results = multiple_targets(self.parser, opts, pargs, stdout_flag=False) # Compare results assert sequence_results == single_results @@ -190,7 +190,7 @@ def test_morphsequence(self, setup_morphsequence): ] ) pargs = [morph_file, testsequence_dir] - s_sequence_results = multiple_morphs(self.parser, opts, pargs, stdout_flag=False) + s_sequence_results = multiple_targets(self.parser, opts, pargs, stdout_flag=False) assert s_sequence_results == sequence_results diff --git a/tests/test_pdfmorphio.py b/tests/test_pdfmorphio.py index 012cca0..d45e3e4 100644 --- a/tests/test_pdfmorphio.py +++ b/tests/test_pdfmorphio.py @@ -4,7 +4,7 @@ import pytest -from diffpy.pdfmorph.pdfmorphapp import create_option_parser, multiple_morphs, single_morph +from diffpy.pdfmorph.pdfmorphapp import create_option_parser, multiple_targets, single_morph # Support Python 2 try: @@ -61,7 +61,7 @@ def ignore_path(line): (opts, pargs) = self.parser.parse_args( [ - "--multiple", + "--multiple-targets", "--sort-by", "temperature", "-s", @@ -72,7 +72,7 @@ def ignore_path(line): ] ) pargs = [morph_file, testsequence_dir] - multiple_morphs(self.parser, opts, pargs, stdout_flag=False) + multiple_targets(self.parser, opts, pargs, stdout_flag=False) # Save a single succinct morph ssm = tmp_succinct.joinpath("single_succinct_morph.cgr") @@ -99,7 +99,7 @@ def ignore_path(line): (opts, pargs) = self.parser.parse_args( [ - "--multiple", + "--multiple-targets", "--sort-by", "temperature", "-s", @@ -111,7 +111,7 @@ def ignore_path(line): ] ) pargs = [morph_file, testsequence_dir] - multiple_morphs(self.parser, opts, pargs, stdout_flag=False) + multiple_targets(self.parser, opts, pargs, stdout_flag=False) # Save a single verbose morph svm = tmp_verbose.joinpath("single_verbose_morph.cgr") diff --git a/tutorial/PDFmorph_manual.pdf b/tutorial/PDFmorph_manual.pdf index 7239202..779e49f 100644 Binary files a/tutorial/PDFmorph_manual.pdf and b/tutorial/PDFmorph_manual.pdf differ