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:** + +* diff --git a/src/diffpy/pdfmorph/morphs/morphshift.py b/src/diffpy/pdfmorph/morphs/morphshift.py index f10a8325..d6d2d2f5 100644 --- a/src/diffpy/pdfmorph/morphs/morphshift.py +++ b/src/diffpy/pdfmorph/morphs/morphshift.py @@ -47,10 +47,19 @@ class MorphShift(Morph): def morph(self, x_morph, y_morph, x_target, y_target): """Apply the shifts.""" + try: + hshift = self.hshift + except AttributeError: + hshift = 0 + try: + vshift = self.vshift + except AttributeError: + 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/src/diffpy/pdfmorph/pdfmorphapp.py b/src/diffpy/pdfmorph/pdfmorphapp.py index 041ddd5e..2a25a5f3 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,25 @@ 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 or opts.vshift is not None: + chain.append(morphs.MorphShift()) + if opts.hshift is not None: + hshift_in = opts.hshift + config["hshift"] = hshift_in + refpars.append("hshift") + if opts.vshift is not None: + vshift_in = opts.vshift + config["vshift"] = vshift_in + refpars.append("vshift") # Smear if opts.smear is not None: smear_in = opts.smear @@ -351,7 +381,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 +462,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 +611,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 +756,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/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 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