Skip to content

Add functionality for multiple morphs in one command #82

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

Merged
merged 18 commits into from
Feb 27, 2024
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
Prev Previous commit
Next Next commit
Add test, temp sort option, fix depreciation
  • Loading branch information
Andrew Yang committed Jul 5, 2023
commit 91fc072eadc5ce3ba3e6868f01e7278b04ff080e
2 changes: 1 addition & 1 deletion diffpy/pdfmorph/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"""

# obtain version information
__version__ = '0.0.1'
from diffpy.pdfmorph.version import __version__

# top-level import
from diffpy.pdfmorph.pdfmorph_api import pdfmorph, morph_default_config, plot_morph
Expand Down
75 changes: 45 additions & 30 deletions diffpy/pdfmorph/pdfmorphapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from pathlib import Path

import numpy
from diffpy.pdfmorph import __version__
from diffpy.pdfmorph.version import __version__
import diffpy.pdfmorph.tools as tools
import diffpy.pdfmorph.pdfplot as pdfplot
import diffpy.pdfmorph.morphs as morphs
Expand All @@ -29,7 +29,7 @@

def create_option_parser():
import optparse
prog_short = sys.argv[0].replace("\\", "/").split("/")[-1] # Program name, compatible w/ all OS paths
prog_short = Path(sys.argv[0]).name # Program name, compatible w/ all OS paths

class CustomParser(optparse.OptionParser):
def __init__(self, *args, **kwargs):
Expand Down Expand Up @@ -71,7 +71,17 @@ def custom_error(self, msg):
action="store_true",
help=f"""Changes usage to \'{prog_short} [options] FILE DIRECTORY\'. FILE
will be morphed with each file in DIRECTORY as target.
Save and plots options disabled when this option is enabled.""",
Files in directory are sorted by alphabetical order unless
--temperature is enabled. Plotting and saving are disabled
when this option is enabled.""",
)
parser.add_option(
'--temperature',
dest="temperature_sort",
action="store_true",
help="""Used with --sequence to sort files in DIRECTORY by temperature.
File names in DIRECTORY should end in _#K.gr or _#K.cgr
to use this option.""",
)
parser.add_option(
'--rmin', type="float", help="Minimum r-value to use for PDF comparisons."
Expand Down Expand Up @@ -186,12 +196,6 @@ def custom_error(self, msg):
dest="plot",
help="Do not show the plot.",
)
group.add_option(
'--usefilenames',
action="store_true",
dest="usefilenames",
help="Use the file names as labels on plot."
)
group.add_option(
'--mlabel',
metavar="MLABEL",
Expand Down Expand Up @@ -258,30 +262,41 @@ def multiple_morphs(parser, opts, pargs, stdout_flag):
if not target_directory.is_dir():
parser.custom_error(f"{target_directory} is not a directory. Go to --help for usage.")

# Sort files in directory
target_list = list(target_directory.iterdir())
if opts.temperature_sort:
# Sort by temperature
target_list = tools.temperature_sort(target_list)
else:
# Default is alphabetical sort
target_list.sort()

# Morph morph_file against all other files in target_directory
results = []
for target_file in target_directory.iterdir():
for target_file in target_list:
# Only morph morph_file against different files in target_directory
if target_file.is_file and morph_file != target_file:
results.append([
target_file.name,
single_morph(parser, opts, [morph_file, target_file], stdout_flag=False),
])

# Input parameters used for every morph
inputs = "\n# Input morphing parameters:"
inputs += f"\n# scale = {opts.scale}"
inputs += f"\n# stretch = {opts.stretch}"
inputs += f"\n# smear = {opts.smear}"
# If print enabled
if stdout_flag:
# Input parameters used for every morph
inputs = "\n# Input morphing parameters:"
inputs += f"\n# scale = {opts.scale}"
inputs += f"\n# stretch = {opts.stretch}"
inputs += f"\n# smear = {opts.smear}"

print(inputs)
print(inputs)

# Results from each morph
for entry in results:
outputs = f"\n# Target: {entry[0]}\n"
outputs += "# Optimized morphing parameters:\n"
outputs += "\n".join(f"# {i[0]} = {i[1]:.6f}" for i in entry[1])
print(outputs)
# Results from each morph
for entry in results:
outputs = f"\n# Target: {entry[0]}\n"
outputs += "# Optimized morphing parameters:\n"
outputs += "\n".join(f"# {i[0]} = {i[1]:.6f}" for i in entry[1])
print(outputs)

return results

Expand Down Expand Up @@ -463,14 +478,14 @@ def single_morph(parser, opts, pargs, stdout_flag):

if opts.plot:
pairlist = [chain.xy_morph_out, chain.xy_target_out]
labels = ["morph", "target"] # Default label names
if opts.usefilenames:
labels = [pargs[0], pargs[1]]
else:
if opts.mlabel is not None:
labels[0] = opts.mlabel
if opts.tlabel is not None:
labels[1] = opts.tlabel
labels = [pargs[0], pargs[1]] # Default is to use file names

# If user chooses labels
if opts.mlabel is not None:
labels[0] = opts.mlabel
if opts.tlabel is not None:
labels[1] = opts.tlabel

# Plot extent defaults to calculation extent
pmin = opts.pmin if opts.pmin is not None else opts.rmin
pmax = opts.pmax if opts.pmax is not None else opts.rmax
Expand Down
42 changes: 42 additions & 0 deletions diffpy/pdfmorph/tests/test_morphsequence.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/usr/bin/env python


import unittest
from pathlib import Path

from diffpy.pdfmorph.pdfmorphapp import create_option_parser, single_morph, multiple_morphs

thisfile = locals().get('__file__', 'file.py')
tests_dir = Path(thisfile).parent.resolve()
testsequence_dir = tests_dir.joinpath("testdata").joinpath("testsequence")


class TestMorphSequence(unittest.TestCase):
def setUp(self):
self.parser = create_option_parser()
filenames = ["174K.gr", "180K.gr", "186K.gr", "192K.gr", "198K.gr", "204K.gr", "210K.gr"]
(self.opts, pargs) = self.parser.parse_args(["--scale", "1", "--stretch", "0", "-n"])
self.testfiles = []
for filename in filenames:
self.testfiles.append(testsequence_dir.joinpath(filename))
return

def test_morphsequence(self):
# Run multiple single morphs
single_results = []
morph_file = self.testfiles[-1]
for target_file in self.testfiles[:-1]:
pargs = [morph_file, target_file]
single_results.append(single_morph(self.parser, self.opts, pargs, stdout_flag=False))
pargs = [morph_file, testsequence_dir]

# Run a morph sequence
sequence_results = multiple_morphs(self.parser, self.opts, pargs, stdout_flag=False)

# Compare results
for idx in range(len(self.testfiles[:-1])):
assert sequence_results[idx][1] == single_results[idx]


if __name__ == '__main__':
unittest.main()
6 changes: 6 additions & 0 deletions diffpy/pdfmorph/tests/test_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ def test_estimateScale(self):
self.assertAlmostEqual(x, scale)
return

def test_nn_value(self):
pass

def test_temperature_sort(self):
pass


# End of class TestRoutines

Expand Down
11 changes: 11 additions & 0 deletions diffpy/pdfmorph/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,14 @@ def nn_value(val, name):
print(negative_value_warning)
return -val
return val


def temperature_sort(filenames):
# Sort files (in list filenames) ending in _#K.gr/_#K.cgr by # rather than alphabetical
for idx in range(len(filenames)):
s_index = filenames[idx].rfind("_") # Start of temperature value
e_index = filenames[idx].rfind("K") # End of temperature value
temp = float(filenames[s_index + 1, e_index])
filenames[idx] = [filenames[idx], temp]
filenames.sort(key=lambda entry: entry[1])
return [entry[0] for entry in filenames]
5 changes: 2 additions & 3 deletions diffpy/pdfmorph/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@
"""Definition of __version__ and __date__ for diffpy.pdfmorph.
"""


# obtain version information
from pkg_resources import get_distribution
from importlib_metadata import version

__version__ = get_distribution('diffpy.pdfmorph').version
__version__ = version('diffpy.pdfmorph')

# we assume that tag_date was used and __version__ ends in YYYYMMDD
__date__ = __version__[-8:-4] + '-' + __version__[-4:-2] + '-' + __version__[-2:]
Expand Down