From bd0c8348c5ba49951c8727e3fc71fb44dc89545e Mon Sep 17 00:00:00 2001 From: Sparks29032 Date: Tue, 12 Nov 2024 16:53:02 -0500 Subject: [PATCH 1/5] Add morph-shift capabilities --- src/diffpy/pdfmorph/morphs/morphshift.py | 5 ++ src/diffpy/pdfmorph/pdfmorphapp.py | 55 ++++++++++++++++--- .../succinct/Morph_Reference_Table.txt | 2 + .../verbose/Morph_Reference_Table.txt | 2 + .../testsaving/verbose/Morphs/mwt_a.cgr | 2 + .../testsaving/verbose/Morphs/mwt_b.cgr | 2 + .../testsaving/verbose/Morphs/mwt_c.cgr | 2 + .../testsaving/verbose/Morphs/mwt_d.cgr | 2 + .../testsaving/verbose/Morphs/mwt_e.cgr | 2 + .../testsaving/verbose/Morphs/mwt_f.cgr | 2 + .../verbose/single_verbose_morph.cgr | 2 + 11 files changed, 71 insertions(+), 7 deletions(-) diff --git a/src/diffpy/pdfmorph/morphs/morphshift.py b/src/diffpy/pdfmorph/morphs/morphshift.py index f10a8325..54db9745 100644 --- a/src/diffpy/pdfmorph/morphs/morphshift.py +++ b/src/diffpy/pdfmorph/morphs/morphshift.py @@ -47,6 +47,11 @@ class MorphShift(Morph): def morph(self, x_morph, y_morph, x_target, y_target): """Apply the shifts.""" + if self.hshift is None: + self.hshift = 0 + if self.vshift is None: + self.vshift = 0 + Morph.morph(self, x_morph, y_morph, x_target, y_target) r = self.x_morph_in - self.hshift self.y_morph_out = numpy.interp(r, self.x_morph_in, self.y_morph_in) diff --git a/src/diffpy/pdfmorph/pdfmorphapp.py b/src/diffpy/pdfmorph/pdfmorphapp.py index 041ddd5e..be63b3b5 100755 --- a/src/diffpy/pdfmorph/pdfmorphapp.py +++ b/src/diffpy/pdfmorph/pdfmorphapp.py @@ -121,12 +121,11 @@ def custom_error(self, msg): help="""Exclude a manipulation from refinement by name. This can appear multiple times.""", ) - group.add_option("--scale", type="float", metavar="SCALE", help="Apply scale factor SCALE.") group.add_option( - "--smear", + "--scale", type="float", - metavar="SMEAR", - help="Smear peaks with a Gaussian of width SMEAR.", + metavar="SCALE", + help="Apply scale factor SCALE.", ) group.add_option( "--stretch", @@ -134,6 +133,12 @@ def custom_error(self, msg): metavar="STRETCH", help="Stretch PDF by a fraction STRETCH.", ) + group.add_option( + "--smear", + type="float", + metavar="SMEAR", + help="Smear peaks with a Gaussian of width SMEAR.", + ) group.add_option( "--slope", type="float", @@ -141,6 +146,18 @@ def custom_error(self, msg): help="""Slope of the baseline. This is used when applying the smear factor. It will be estimated if not provided.""", ) + group.add_option( + "--hshift", + type="float", + metavar="HSHIFT", + help="Shift the PDF horizontally by HSHIFT to the right.", + ) + group.add_option( + "--vshift", + type="float", + metavar="VSHIFT", + help="Shift the PDF vertically by VSHIFT upward.", + ) group.add_option( "--qdamp", type="float", @@ -318,6 +335,8 @@ def single_morph(parser, opts, pargs, stdout_flag=True): scale_in = "None" stretch_in = "None" smear_in = "None" + hshift_in = "None" + vshift_in = "None" config = {} config["rmin"] = opts.rmin config["rmax"] = opts.rmax @@ -336,14 +355,33 @@ def single_morph(parser, opts, pargs, stdout_flag=True): if opts.scale is not None: scale_in = opts.scale chain.append(morphs.MorphScale()) - config["scale"] = opts.scale + config["scale"] = scale_in refpars.append("scale") # Stretch if opts.stretch is not None: stretch_in = opts.stretch chain.append(morphs.MorphStretch()) - config["stretch"] = opts.stretch + config["stretch"] = stretch_in refpars.append("stretch") + # Shift + if opts.hshift is not None: + hshift_in = opts.hshift + chain.append(morphs.MorphShift()) + config["hshift"] = hshift_in + refpars.append("hshift") + if opts.vshift is None: + vshift_in = 0 + config["vshift"] = vshift_in + refpars.append("vshift") + if opts.vshift is not None: + vshift_in = opts.vshift + chain.append(morphs.MorphShift()) + config["vshift"] = vshift_in + refpars.append("vshift") + if opts.hshift is None: + hshift_in = 0 + config["hshift"] = hshift_in + refpars.append("hshift") # Smear if opts.smear is not None: smear_in = opts.smear @@ -351,7 +389,7 @@ def single_morph(parser, opts, pargs, stdout_flag=True): chain.append(morphs.MorphSmear()) chain.append(helpers.TransformXtalRDFtoPDF()) refpars.append("smear") - config["smear"] = opts.smear + config["smear"] = smear_in # Set baselineslope if not given config["baselineslope"] = opts.baselineslope if opts.baselineslope is None: @@ -432,6 +470,7 @@ def single_morph(parser, opts, pargs, stdout_flag=True): # Input morph parameters morph_inputs = {"scale": scale_in, "stretch": stretch_in, "smear": smear_in} + morph_inputs.update({"hshift": hshift_in, "vshift": vshift_in}) # Output morph parameters morph_results = dict(config.items()) @@ -580,6 +619,7 @@ def multiple_targets(parser, opts, pargs, stdout_flag=True): target_file_names.append(key) morph_inputs = {"scale": opts.scale, "stretch": opts.stretch, "smear": opts.smear} + morph_inputs.update({"hshift": opts.hshift, "vshift": opts.vshift}) try: # Print summary of morphs to terminal and to file (if requested) @@ -724,6 +764,7 @@ def multiple_morphs(parser, opts, pargs, stdout_flag=True): morph_file_names.append(key) morph_inputs = {"scale": opts.scale, "stretch": opts.stretch, "smear": opts.smear} + morph_inputs.update({"hshift": opts.hshift, "vshift": opts.vshift}) try: # Print summary of morphs to terminal and to file (if requested) diff --git a/tests/testdata/testsaving/succinct/Morph_Reference_Table.txt b/tests/testdata/testsaving/succinct/Morph_Reference_Table.txt index 43d11f71..d1b30b88 100644 --- a/tests/testdata/testsaving/succinct/Morph_Reference_Table.txt +++ b/tests/testdata/testsaving/succinct/Morph_Reference_Table.txt @@ -6,6 +6,8 @@ # scale = None # stretch = None # smear = None +# hshift = None +# vshift = None # Labels: [Target] [Temperature] [Pearson] [Rw] f_180K.gr 180.0 0.999810 0.020141 diff --git a/tests/testdata/testsaving/verbose/Morph_Reference_Table.txt b/tests/testdata/testsaving/verbose/Morph_Reference_Table.txt index 175787a7..6fc523bc 100644 --- a/tests/testdata/testsaving/verbose/Morph_Reference_Table.txt +++ b/tests/testdata/testsaving/verbose/Morph_Reference_Table.txt @@ -6,6 +6,8 @@ # scale = None # stretch = None # smear = None +# hshift = None +# vshift = None # Target: f_180K.gr # Optimized morphing parameters: diff --git a/tests/testdata/testsaving/verbose/Morphs/mwt_a.cgr b/tests/testdata/testsaving/verbose/Morphs/mwt_a.cgr index 84e9d75e..f9335ccf 100644 --- a/tests/testdata/testsaving/verbose/Morphs/mwt_a.cgr +++ b/tests/testdata/testsaving/verbose/Morphs/mwt_a.cgr @@ -5,6 +5,8 @@ # scale = None # stretch = None # smear = None +# hshift = None +# vshift = None # Optimized morphing parameters: # rmin = 0.000000 diff --git a/tests/testdata/testsaving/verbose/Morphs/mwt_b.cgr b/tests/testdata/testsaving/verbose/Morphs/mwt_b.cgr index 2c58d1b3..40186c4b 100644 --- a/tests/testdata/testsaving/verbose/Morphs/mwt_b.cgr +++ b/tests/testdata/testsaving/verbose/Morphs/mwt_b.cgr @@ -5,6 +5,8 @@ # scale = None # stretch = None # smear = None +# hshift = None +# vshift = None # Optimized morphing parameters: # rmin = 0.000000 diff --git a/tests/testdata/testsaving/verbose/Morphs/mwt_c.cgr b/tests/testdata/testsaving/verbose/Morphs/mwt_c.cgr index 3c357184..6bf1eb5f 100644 --- a/tests/testdata/testsaving/verbose/Morphs/mwt_c.cgr +++ b/tests/testdata/testsaving/verbose/Morphs/mwt_c.cgr @@ -5,6 +5,8 @@ # scale = None # stretch = None # smear = None +# hshift = None +# vshift = None # Optimized morphing parameters: # rmin = 0.000000 diff --git a/tests/testdata/testsaving/verbose/Morphs/mwt_d.cgr b/tests/testdata/testsaving/verbose/Morphs/mwt_d.cgr index ea201276..e5023b18 100644 --- a/tests/testdata/testsaving/verbose/Morphs/mwt_d.cgr +++ b/tests/testdata/testsaving/verbose/Morphs/mwt_d.cgr @@ -5,6 +5,8 @@ # scale = None # stretch = None # smear = None +# hshift = None +# vshift = None # Optimized morphing parameters: # rmin = 0.000000 diff --git a/tests/testdata/testsaving/verbose/Morphs/mwt_e.cgr b/tests/testdata/testsaving/verbose/Morphs/mwt_e.cgr index 78aa564e..1d06ae2e 100644 --- a/tests/testdata/testsaving/verbose/Morphs/mwt_e.cgr +++ b/tests/testdata/testsaving/verbose/Morphs/mwt_e.cgr @@ -5,6 +5,8 @@ # scale = None # stretch = None # smear = None +# hshift = None +# vshift = None # Optimized morphing parameters: # rmin = 0.000000 diff --git a/tests/testdata/testsaving/verbose/Morphs/mwt_f.cgr b/tests/testdata/testsaving/verbose/Morphs/mwt_f.cgr index 53eb1971..afd8b039 100644 --- a/tests/testdata/testsaving/verbose/Morphs/mwt_f.cgr +++ b/tests/testdata/testsaving/verbose/Morphs/mwt_f.cgr @@ -5,6 +5,8 @@ # scale = None # stretch = None # smear = None +# hshift = None +# vshift = None # Optimized morphing parameters: # rmin = 0.000000 diff --git a/tests/testdata/testsaving/verbose/single_verbose_morph.cgr b/tests/testdata/testsaving/verbose/single_verbose_morph.cgr index 84e9d75e..f9335ccf 100644 --- a/tests/testdata/testsaving/verbose/single_verbose_morph.cgr +++ b/tests/testdata/testsaving/verbose/single_verbose_morph.cgr @@ -5,6 +5,8 @@ # scale = None # stretch = None # smear = None +# hshift = None +# vshift = None # Optimized morphing parameters: # rmin = 0.000000 From 76d1bd118f924733b3d4c313754a792ddf859e92 Mon Sep 17 00:00:00 2001 From: Sparks29032 Date: Tue, 12 Nov 2024 16:59:02 -0500 Subject: [PATCH 2/5] Isolating shifting morphs --- src/diffpy/pdfmorph/morphs/morphshift.py | 8 ++++++-- src/diffpy/pdfmorph/pdfmorphapp.py | 8 -------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/diffpy/pdfmorph/morphs/morphshift.py b/src/diffpy/pdfmorph/morphs/morphshift.py index 54db9745..2422c282 100644 --- a/src/diffpy/pdfmorph/morphs/morphshift.py +++ b/src/diffpy/pdfmorph/morphs/morphshift.py @@ -47,9 +47,13 @@ class MorphShift(Morph): def morph(self, x_morph, y_morph, x_target, y_target): """Apply the shifts.""" - if self.hshift is None: + try: + self.hshift + except AttributeError: self.hshift = 0 - if self.vshift is None: + try: + self.vshift + except AttributeError: self.vshift = 0 Morph.morph(self, x_morph, y_morph, x_target, y_target) diff --git a/src/diffpy/pdfmorph/pdfmorphapp.py b/src/diffpy/pdfmorph/pdfmorphapp.py index be63b3b5..8f99c048 100755 --- a/src/diffpy/pdfmorph/pdfmorphapp.py +++ b/src/diffpy/pdfmorph/pdfmorphapp.py @@ -369,19 +369,11 @@ def single_morph(parser, opts, pargs, stdout_flag=True): chain.append(morphs.MorphShift()) config["hshift"] = hshift_in refpars.append("hshift") - if opts.vshift is None: - vshift_in = 0 - config["vshift"] = vshift_in - refpars.append("vshift") if opts.vshift is not None: vshift_in = opts.vshift chain.append(morphs.MorphShift()) config["vshift"] = vshift_in refpars.append("vshift") - if opts.hshift is None: - hshift_in = 0 - config["hshift"] = hshift_in - refpars.append("hshift") # Smear if opts.smear is not None: smear_in = opts.smear From fad4f074e70509d1f41ab31cb360c8bc6b87db24 Mon Sep 17 00:00:00 2001 From: Sparks29032 Date: Tue, 12 Nov 2024 17:28:19 -0500 Subject: [PATCH 3/5] Add tests --- src/diffpy/pdfmorph/morphs/morphshift.py | 12 +++--- tests/test_morphshift.py | 52 ++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 tests/test_morphshift.py diff --git a/src/diffpy/pdfmorph/morphs/morphshift.py b/src/diffpy/pdfmorph/morphs/morphshift.py index 2422c282..d6d2d2f5 100644 --- a/src/diffpy/pdfmorph/morphs/morphshift.py +++ b/src/diffpy/pdfmorph/morphs/morphshift.py @@ -48,18 +48,18 @@ class MorphShift(Morph): def morph(self, x_morph, y_morph, x_target, y_target): """Apply the shifts.""" try: - self.hshift + hshift = self.hshift except AttributeError: - self.hshift = 0 + hshift = 0 try: - self.vshift + vshift = self.vshift except AttributeError: - self.vshift = 0 + vshift = 0 Morph.morph(self, x_morph, y_morph, x_target, y_target) - r = self.x_morph_in - self.hshift + r = self.x_morph_in - hshift self.y_morph_out = numpy.interp(r, self.x_morph_in, self.y_morph_in) - self.y_morph_out += self.vshift + self.y_morph_out += vshift return self.xyallout diff --git a/tests/test_morphshift.py b/tests/test_morphshift.py new file mode 100644 index 00000000..2e1c0bbd --- /dev/null +++ b/tests/test_morphshift.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python + + +import os + +import numpy +import pytest + +from diffpy.pdfmorph.morphs.morphshift import MorphShift + +# useful variables +thisfile = locals().get("__file__", "file.py") +tests_dir = os.path.dirname(os.path.abspath(thisfile)) +# testdata_dir = os.path.join(tests_dir, 'testdata') + + +class TestMorphShift: + @pytest.fixture + def setup(self): + self.hshift = 2.0 + self.vshift = 3.0 + + # Original dataset goes from 0.1 to 5.0 + self.x_morph = numpy.arange(0.01, 5 + self.hshift, 0.01) + self.y_morph = numpy.arange(0.01, 5 + self.hshift, 0.01) + + # New dataset is moved to the right by 2.0 and upward by 3.0 + self.x_target = numpy.arange(0.01 + self.hshift, 5 + self.hshift, 0.01) + self.y_target = numpy.arange(0.01 + self.vshift, 5 + self.vshift, 0.01) + return + + def test_morph(self, setup): + """check MorphScale.morph()""" + config = {"hshift": self.hshift, "vshift": self.vshift} + morph = MorphShift(config) + + x_morph, y_morph, x_target, y_target = morph(self.x_morph, self.y_morph, self.x_target, self.y_target) + + # Only care about the shifted data past the shift + # Everything to left of shift is outside our input data domain + assert numpy.allclose(y_morph[x_morph > self.hshift], y_target) + assert numpy.allclose(self.x_target, x_target) + assert numpy.allclose(self.y_target, y_target) + return + + +# End of class TestMorphScale + +if __name__ == "__main__": + TestMorphShift() + +# End of file From a3de510fa5e7f0b25727fc622c5c3b53397627f3 Mon Sep 17 00:00:00 2001 From: Sparks29032 Date: Tue, 12 Nov 2024 17:29:31 -0500 Subject: [PATCH 4/5] news --- news/morphshift.rst | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 news/morphshift.rst diff --git a/news/morphshift.rst b/news/morphshift.rst new file mode 100644 index 00000000..71a2714a --- /dev/null +++ b/news/morphshift.rst @@ -0,0 +1,23 @@ +**Added:** + +* Shifting morph for vertical and horizontal shifts. + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* From 641b5e7de84e5766fcd0a78f2eef23e81469d9b7 Mon Sep 17 00:00:00 2001 From: Sparks29032 Date: Tue, 12 Nov 2024 17:35:25 -0500 Subject: [PATCH 5/5] Prevent duplication of morphshift --- src/diffpy/pdfmorph/pdfmorphapp.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/diffpy/pdfmorph/pdfmorphapp.py b/src/diffpy/pdfmorph/pdfmorphapp.py index 8f99c048..2a25a5f3 100755 --- a/src/diffpy/pdfmorph/pdfmorphapp.py +++ b/src/diffpy/pdfmorph/pdfmorphapp.py @@ -364,14 +364,14 @@ def single_morph(parser, opts, pargs, stdout_flag=True): config["stretch"] = stretch_in refpars.append("stretch") # Shift + if opts.hshift is not None or opts.vshift is not None: + chain.append(morphs.MorphShift()) if opts.hshift is not None: hshift_in = opts.hshift - chain.append(morphs.MorphShift()) config["hshift"] = hshift_in refpars.append("hshift") if opts.vshift is not None: vshift_in = opts.vshift - chain.append(morphs.MorphShift()) config["vshift"] = vshift_in refpars.append("vshift") # Smear