Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding multiple morphs for single target #145

Merged
merged 4 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
Binary file modified doc/manual/pdfmorph.pdf
Binary file not shown.
34 changes: 17 additions & 17 deletions doc/manual/pdfmorph.texinfo
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -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.
Expand All @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 <MORPHED_FILE> <TARGET_DIRECTORY>
Expand All @@ -1034,25 +1034,25 @@ 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{<PARAM_NAME> = <PARAM_VALUE>} 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
case-insensitive search. Numerical @code{PARAM_VALUE} will be sorted in ascending order and
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
Expand All @@ -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.
Expand Down
6 changes: 3 additions & 3 deletions doc/source/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -203,15 +203,15 @@ 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``
and directory was the cwd, which should be ``morphMultiple``.
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 ``<parameter_name> = <parameter_value>`` and are located
Expand All @@ -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.
Expand Down
23 changes: 23 additions & 0 deletions news/multiple_morphs.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
**Added:**

* --multiple-morphs: morph multiple files against a single target

**Changed:**

* --multiple changed to --multiple-targets for clarity

**Deprecated:**

* <news item>

**Removed:**

* <news item>

**Fixed:**

* <news item>

**Security:**

* <news item>
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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',
Expand Down
35 changes: 28 additions & 7 deletions src/diffpy/pdfmorph/pdfmorph_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -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_<target file name>.cgr'.
Expand All @@ -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
-------
Expand All @@ -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


Expand All @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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]
Expand All @@ -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():
Expand Down Expand Up @@ -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)
Expand Down
Loading