Skip to content

Commit d7a9d30

Browse files
authored
Merge pull request #145 from diffpy/multiple_morphs
Adding multiple morphs for single target
2 parents 2bc6ee8 + e4e4d89 commit d7a9d30

10 files changed

+262
-56
lines changed

doc/manual/pdfmorph.pdf

168 Bytes
Binary file not shown.

doc/manual/pdfmorph.texinfo

+17-17
Original file line numberDiff line numberDiff line change
@@ -462,10 +462,10 @@ Long Yang.
462462
@item Let us start by getting the @math{R_W} of @code{SrFe2As2_150K.gr}
463463
compared to the other, higher-temperature PDFs in the directory. Run
464464
@example
465-
pdfmorph SrFe2As2_150K.gr . --multiple
465+
pdfmorph SrFe2As2_150K.gr . --multiple-targets
466466
@end example
467467
@itemize
468-
@item The @code{--multiple} tag tells @code{PDFmorph} to compare the morphed file
468+
@item The @code{--multiple-targets} tag tells @code{PDFmorph} to compare the morphed file
469469
@code{SrFe2As2_150K.gr} against all PDFs in a directory. The directory we have
470470
supplied is @code{.}, which is shorthand for the current working directory.
471471
In our case, this is the @code{morphMultiple} directory.
@@ -489,7 +489,7 @@ included are temperature, wavelength, and composition.}
489489
@end float
490490
@item By running
491491
@example
492-
pdfmorph SrFe2As2_150K.gr . --multiple --sort-by=temperature
492+
pdfmorph SrFe2As2_150K.gr . --multiple-targets --sort-by=temperature
493493
@end example
494494
we can sort the plotted @math{R_W} values by the temperature parameter included within each file.
495495
@itemize
@@ -506,7 +506,7 @@ instead of @code{temperature}.
506506
a phase change. To be more certain, let us apply morphs to take into account isotropic expansion and differences
507507
in incident flux (stretching and scaling).
508508
@example
509-
pdfmorph SrFe2As2_150K.gr . --scale=1 --stretch=0 --multiple \
509+
pdfmorph SrFe2As2_150K.gr . --scale=1 --stretch=0 --multiple-targets \
510510
--sort-by=temperature
511511
@end example
512512
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.
517517
@item We can also change what is being plotted in the ordinate using @code{--plot-parameter}. In our case,
518518
it is useful to look at the @code{stretch} factor
519519
@example
520-
pdfmorph SrFe2As2_150K.gr . --scale=1 --stretch=0 --multiple \
520+
pdfmorph SrFe2As2_150K.gr . --scale=1 --stretch=0 --multiple-targets \
521521
--sort-by=temperature --plot-parameter=stretch
522522
@end example
523523
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}.
533533
@end float
534534
@item Finally, let us save all the morphed PDFs into a directory named @code{savedMorphs}.
535535
@example
536-
pdfmorph SrFe2As2_150K.gr . --scale=1 --stretch=0 --multiple \
536+
pdfmorph SrFe2As2_150K.gr . --scale=1 --stretch=0 --multiple-targets \
537537
--sort-by=temperature --plot-parameter=stretch \
538538
--save=savedMorphs
539539
@end example
@@ -877,8 +877,8 @@ the residual with the target PDF.
877877
@noindent @code{-s NAME, --save=NAME}
878878
@* @indent Save the morphed PDF into a file named @code{NAME}. You can use
879879
@code{-} to save to @code{stdout} instead.
880-
When you have the @code{--multiple} tag enabled, multiple morphed PDFs are
881-
generated. Using this command with the @code{--multiple} tag will save all
880+
When you have the @code{--multiple-targets} tag enabled, multiple morphed PDFs are
881+
generated. Using this command with the @code{--multiple-targets} tag will save all
882882
these morphs into a directory named @code{NAME} as well as a @code{.txt}
883883
file summary of refined morph parameters (if applicable) and @math{R_W}
884884
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}.
981981
@noindent @titlefont{@b{Plot options}}
982982

983983
These options control plotting. The morphed and target PDFs will be plotted against each other with a
984-
difference curve shown below. The following changes occur when @code{--multiple} is enabled.
984+
difference curve shown below. The following changes occur when @code{--multiple-targets} is enabled.
985985
(1) The @math{R_W} for each morphed PDF compared to the target will be plotted unless
986986
another parameter is specified by @code{--plot-parameter}. (2) The plot will be a bar chart
987987
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
10201020

10211021
@noindent @titlefont{@b{Multiple morphs}}
10221022

1023-
@code{PDFmorph} allows one to morph one PDF against multiple different targets when @code{--multiple}
1023+
@code{PDFmorph} allows one to morph one PDF against multiple different targets when @code{--multiple-targets}
10241024
is enabled. See @code{-s} and the description under "Plot options" for how saving and plotting
1025-
change when @code{--multiple} is enabled.
1025+
change when @code{--multiple-targets} is enabled.
10261026

1027-
@noindent @code{--multiple}
1027+
@noindent @code{--multiple-targets}
10281028
@* @indent Changes usage of @code{PDFmorph} to
10291029
@example
10301030
pdfmorph <MORPHED_FILE> <TARGET_DIRECTORY>
@@ -1034,25 +1034,25 @@ in the directory @code{TARGET_DIRECTORY} as the target. Files in @code{TARGET_DI
10341034
be sorted in ASCII sort order order unless a sorting parameter is specified by @code{sort-by}.
10351035

10361036
@noindent @code{--sort-by=FIELD}
1037-
@* @indent Used with @code{--multiple}. Sort the files in @code{TARGET_DIRECTORY} by some parameter
1037+
@* @indent Used with @code{--multiple-targets}. Sort the files in @code{TARGET_DIRECTORY} by some parameter
10381038
named @code{FIELD}. Parameters can be specified within each target PDF file by lines of the form
10391039
@code{<PARAM_NAME> = <PARAM_VALUE>} in the header (anywhere above the @math{r} versus @math{G(r)}
10401040
data table). @code{PDFmorph} will attempt to find a parameter named @code{FIELD} using a
10411041
case-insensitive search. Numerical @code{PARAM_VALUE} will be sorted in ascending order and
10421042
non-numerical ones will be sorted in ASCII sort order.
10431043

10441044
@noindent @code{--reverse}
1045-
@* @indent Used with @code{--multiple}. Sort the files in @code{TARGET_DIRECTORY} in reverse
1045+
@* @indent Used with @code{--multiple-targets}. Sort the files in @code{TARGET_DIRECTORY} in reverse
10461046
ASCII sort order. If a parameter is given by @code{--sort-by}, reverse the order given by
10471047
@code{--sort-by}.
10481048

10491049
@noindent @code{--serial-file=SERIALFILE}
1050-
@* @indent Used with @code{--multiple} and @code{--sort-by}. Look for @code{FIELD} in a serial
1050+
@* @indent Used with @code{--multiple-targets} and @code{--sort-by}. Look for @code{FIELD} in a serial
10511051
file named @code{SERIALFILE} instead. Only serial file types supported by
10521052
@url{https://www.diffpy.org/diffpy.utils, diffpy.utils} such as @code{.json} are allowed.
10531053

10541054
@noindent @code{--save-names-file=NAMESFILE}
1055-
@* @indent Used with @code{--multiple} and @code{-s}. Specify names for each manipulated PDF when
1055+
@* @indent Used with @code{--multiple-targets} and @code{-s}. Specify names for each manipulated PDF when
10561056
saving using a serial file named @code{NAMESFILE}. The format of @code{NAMESFILE} should be
10571057
as follows: (1) Each target PDF file name is an entry in @code{NAMESFILE}. (2) For each entry,
10581058
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.
10761076
such as @code{.json} are allowed.
10771077

10781078
@noindent @code{--plot-parameter=PLOTPARAM}
1079-
@* @indent Used with @code{--multiple} and when plotting is enabled. Choose a parameter @code{PLOTPARAM}
1079+
@* @indent Used with @code{--multiple-targets} and when plotting is enabled. Choose a parameter @code{PLOTPARAM}
10801080
to plot for each morph. When not specified, the @math{R_W} values for each morphed PDF compared to the
10811081
target PDFs will be plotted. This option is not case sensitive meaning @code{--plot-parameter=Scale} and
10821082
@code{--plot-parameter=scale} will both cause the parameter @code{scale} to be plotted.

doc/source/quickstart.rst

+3-3
Original file line numberDiff line numberDiff line change
@@ -203,15 +203,15 @@ selected directory and plot resulting :math:`R_w` values from each morph.
203203
2. Let us start by getting the Rw of ``SrFe2As2_150K.gr`` compared to all other files in the
204204
directory. Run ::
205205

206-
pdfmorph SrFe2As2_150K.gr . --multiple
206+
pdfmorph SrFe2As2_150K.gr . --multiple-targets
207207

208208
The multiple tag indicates we are comparing PDF file (first input) against all PDFs in
209209
a directory (second input). Our choice of file was ``SeFe2As2_150K.gr``
210210
and directory was the cwd, which should be ``morphMultiple``.
211211
3. After running this, we get chart of Rw values for each target file. However, this chart can
212212
be a bit confusing to interpret. To get a more understandable plot, run ::
213213

214-
pdfmorph SrFe2As2_150K.gr . --multiple --sort-by=temperature
214+
pdfmorph SrFe2As2_150K.gr . --multiple-targets --sort-by=temperature
215215

216216
This plots the Rw against the temperature parameter value provided at the top of each file.
217217
Parameters are entries of the form ``<parameter_name> = <parameter_value>`` and are located
@@ -220,7 +220,7 @@ selected directory and plot resulting :math:`R_w` values from each morph.
220220
To confirm, let us now apply morphs onto ``SrFe2As2_150K.gr`` with all other files in ``morphMultiple``
221221
as targets ::
222222

223-
pdfmorph --scale=1 --stretch=0 SrFe2As2_150K.gr . --multiple --sort-by=temperature
223+
pdfmorph --scale=1 --stretch=0 SrFe2As2_150K.gr . --multiple-targets --sort-by=temperature
224224

225225
Note that we are not applying a smear since it takes a long time to apply and does not significantly
226226
change the Rw values in this example.

news/multiple_morphs.rst

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
**Added:**
2+
3+
* --multiple-morphs: morph multiple files against a single target
4+
5+
**Changed:**
6+
7+
* --multiple changed to --multiple-targets for clarity
8+
9+
**Deprecated:**
10+
11+
* <news item>
12+
13+
**Removed:**
14+
15+
* <news item>
16+
17+
**Fixed:**
18+
19+
* <news item>
20+
21+
**Security:**
22+
23+
* <news item>

pyproject.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ maintainers = [
1414
description = "Tools for manipulating and comparing PDF profiles"
1515
keywords = ['diffpy', 'pdf', 'data interpretation']
1616
readme = "README.rst"
17-
requires-python = ">=3.11, <3.14"
17+
requires-python = ">=3.10, <3.14"
1818
classifiers = [
1919
'Development Status :: 5 - Production/Stable',
2020
'Environment :: Console',
@@ -25,6 +25,7 @@ classifiers = [
2525
'Operating System :: Microsoft :: Windows',
2626
'Operating System :: POSIX',
2727
'Operating System :: Unix',
28+
'Programming Language :: Python :: 3.10',
2829
'Programming Language :: Python :: 3.11',
2930
'Programming Language :: Python :: 3.12',
3031
'Programming Language :: Python :: 3.13',

src/diffpy/pdfmorph/pdfmorph_io.py

+28-7
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ def create_morphs_directory(save_directory):
124124
return str(morphs_subdirectory.resolve())
125125

126126

127-
def get_multisave_names(target_list: list, save_names_file=None):
127+
def get_multisave_names(target_list: list, save_names_file=None, mm=False):
128128
"""Create or import a dictionary that specifies names to save morphs as.
129129
First attempt to import names from a specified file. If names for certain morphs not found,
130130
use default naming scheme: 'Morph_with_Target_<target file name>.cgr'.
@@ -134,9 +134,11 @@ def get_multisave_names(target_list: list, save_names_file=None):
134134
Parameters
135135
----------
136136
target_list: list
137-
Target PDFs used for each morph.
137+
Target (or Morph if mm enabled) PDFs used for each morph.
138138
save_names_file
139139
Name of file to import save names dictionary from (default None).
140+
mm: bool
141+
Rather than multiple targets, multiple morphs are being done.
140142
141143
Returns
142144
-------
@@ -154,7 +156,12 @@ def get_multisave_names(target_list: list, save_names_file=None):
154156
# Apply default naming scheme to missing targets
155157
for target_file in target_list:
156158
if target_file.name not in save_names.keys():
157-
save_names.update({target_file.name: {__save_morph_as__: f"Morph_with_Target_{target_file.stem}.cgr"}})
159+
if not mm:
160+
save_names.update(
161+
{target_file.name: {__save_morph_as__: f"Morph_with_Target_{target_file.stem}.cgr"}}
162+
)
163+
else:
164+
save_names.update({target_file.name: {__save_morph_as__: f"Morph_of_{target_file.stem}.cgr"}})
158165
return save_names
159166

160167

@@ -169,6 +176,7 @@ def multiple_morph_output(
169176
target_directory=None,
170177
verbose=False,
171178
stdout_flag=False,
179+
mm=False,
172180
):
173181
"""Helper function for printing details about a series of multiple morphs.
174182
Handles both printing to terminal and printing to a file.
@@ -196,6 +204,9 @@ def multiple_morph_output(
196204
Print additional summary details when True (default False).
197205
stdout_flag: bool
198206
Print to terminal when True (default False).
207+
mm: bool
208+
Multiple morphs done with a single target rather than multiple targets for a single morphed file.
209+
Swaps morph and target in the code.
199210
"""
200211

201212
# Input parameters used for every morph
@@ -207,7 +218,10 @@ def multiple_morph_output(
207218
if verbose:
208219
# Output for every morph (information repeated in a succinct table below)
209220
for target in morph_results.keys():
210-
output = f"\n# Target: {target}\n"
221+
if not mm:
222+
output = f"\n# Target: {target}\n"
223+
else:
224+
output = f"\n# Morph: {target}\n"
211225
output += "# Optimized morphing parameters:\n"
212226
output += "\n".join(
213227
f"# {param} = {morph_results[target][param]:.6f}" for param in morph_results[target]
@@ -218,7 +232,10 @@ def multiple_morph_output(
218232
tabulated_results = tabulate_results(morph_results)
219233

220234
# Table labels
221-
labels = "\n# Labels: [Target]"
235+
if not mm:
236+
labels = "\n# Labels: [Target]"
237+
else:
238+
labels = "\n# Labels: [Morph]"
222239
if field is not None:
223240
labels += f" [{field}]"
224241
for param in tabulated_results.keys():
@@ -247,8 +264,12 @@ def multiple_morph_output(
247264
target_path_name = str(Path(target_directory).resolve())
248265

249266
header = "# Data generated by pdfmorph\n"
250-
header += f"# from morphing {morph_path_name}\n"
251-
header += f"# with target directory {target_path_name}"
267+
if not mm:
268+
header += f"# from morphing {morph_path_name}\n"
269+
header += f"# with target directory {target_path_name}"
270+
else:
271+
header += f"# from morphing directory {target_path_name}\n"
272+
header += f"# with target {morph_path_name}"
252273
reference_table = Path(save_directory).joinpath("Morph_Reference_Table.txt")
253274
with open(reference_table, "w") as reference:
254275
print(f"{header}\n{inputs}\n{verbose_outputs}{table}", file=reference)

0 commit comments

Comments
 (0)