diff --git a/doc/source/squeeze.rst b/doc/source/squeeze.rst new file mode 100644 index 00000000..04a5acac --- /dev/null +++ b/doc/source/squeeze.rst @@ -0,0 +1,404 @@ +.. _squeeze: + +morphsqueeze Tutorial +##################### + +Welcome! This will be a quick tutorial to accquaint users with ``diffpy.morph`` +and some of what it can do. To see more details and definitions about +the morphs please see the publication describing ``diffpy.morph``. + +To be published: + +* + + +As we described in the README and installation instructions, please make +sure that you are familiar with working with your command line terminal +before using this application. + +Before you've started this tutorial, please ensure that you've installed +all necessary software and dependencies. + +In this tutorial, we will demonstrate how to use ``diffpy.morph`` to compare +two +PDFs measured from the same material at different temperatures. +The morphs showcased include "stretch", "scale", and "smear". + +Basic diffpy.morph Workflow +=========================== + + 1. Open your Terminal or Command Prompt. + + 2. If it's not active already, activate your diffpy.morph-equipped + conda environment by typing in :: + + conda activate + + + * If you need to list your available conda environments, + run the command ``conda info --envs`` or + ``conda env list`` + + * Run the ``diffpy.morph --help`` command and read over the + info on that page for a brief overview of some of what we will + explore in this tutorial. + + 3. Using the ``mkdir`` command, create a directory where you'll + store the tutorial PDF files and use the ``cd`` command to change + into that directory. You can download the tutorial files + :download:`here <../../tutorial/tutorialData.zip>`. + Then, ``cd`` into the ``tutorialData`` directory. + + * The files in this dataset were collected by Soham Banerjee + at Brookhaven National Laboratory in Upton, New York. + + * The files are PDF data collected on Iridium Telluride with + 20% Rhodium Doping (IrRhTe2) with the first file (01) collected + at 10K and the last (44) at 300K. The samples increase in + temperature as their numbers increase. The "C" in their names + indicates that they have undergone cooling. + + * Note that these files have the ``.gr`` extension, which + indicates that they are measured PDFs. The ``.cgr`` file + extension indicates that a file is a calculated PDF, such as + those generated by the + `PDFgui `_ + program. + + 4. First, we will run the ``diffpy.morph`` application without any morphing + and only using one PDF. Type the following command into your + command line :: + + diffpy.morph darkSub_rh20_C_01.gr darkSub_rh20_C_01.gr + + This should produce two PDF curves which are congruent, resulting + in a flat green line underneath them. + + 5. Now, we will see ``diffpy.morph`` run with two different PDFs and no + morphing. Type the following command into your command line :: + + diffpy.morph darkSub_rh20_C_01.gr darkSub_rh20_C_44.gr + + Without morphing, the difference Rw = 0.407. This indicates that + the two PDFs vary drastically. + + * While running the ``diffpy.morph`` command, it is important + to remember that the first PDF file argument you provide + (in this case, ``darkSub_rh20_C_01.gr``) is the PDF which + will get morphed, while the second PDF file argument you + provide (here, ``darkSub_rh20_C_44.gr``) is the PDF which + acts as the model and does not get morphed. Hereinafter, + we will refer to the first PDF argument as the "morph" + and the second as the "target", as the ``diffpy.morph`` display + does. + + .. figure:: images/qs_tutorial_unmorphed.png + :align: center + :figwidth: 100% + + Using ``diffpy.morph`` to compare two different PDFs without morphing. + + 6. Now, we will start the morphing process, which requires us to + provide initial guesses for our scaling factor, Gaussian smear, + and stretch, separately. We will start with the scaling factor. + Begin by typing the command :: + + diffpy.morph --scale=2 -a darkSub_rh20_C_01.gr darkSub_rh20_C_44.gr + + Now, the difference Rw = 1.457, a significant increase from our + value previously. We must modify our initial value for the + scaling factor and do so until we see a reduction in the + difference Rw from the unmorphed value. Type :: + + diffpy.morph --scale=0.9 -a darkSub_rh20_C_01.gr darkSub_rh20_C_44.gr + + The difference Rw is now 0.351, lower than our unmorphed + example's value. To see ``diffpy.morph`` optimize the scale factor, + simply drop ``-a`` from the command and type :: + + diffpy.morph --scale=0.9 darkSub_rh20_C_01.gr darkSub_rh20_C_44.gr + + ``diffpy.morph``, given a reasonable initial guess, will use find the + optimal value for each morphing feature. Here, we see that + ``diffpy.morph`` displays ``scale = 0.799025`` in the command prompt, + meaning that it has found this to be the most optimal value for + the scale factor. The difference Rw = 0.330, indicating a + better fit than our reasonable initial guess. + + * It is the choice of the user whether or not to run values + before removing ``-a`` when analyzing data with ``diffpy.morph``. + By including it, you allow the possibility to move towards + convergence before allowing the program to optimize by + removing it; when including it, you may reach a highly + optimized value on the first guess or diverge greatly. + In this tutorial, we will use it every time to check + for convergence. + + .. figure:: images/qs_tutorial_scaled.png + :align: center + :figwidth: 100% + + ``diffpy.morph`` found an optimal value for the scale factor. + + 7. Now, we will examine the Gaussian smearing factor. We provide an + initial guess by typing :: + + diffpy.morph --scale=0.8 --smear=0.5 -a darkSub_rh20_C_01.gr darkSub_rh20_C_44.gr + + And viewing the results. We've tailored our scale factor to be + close to the value given by ``diffpy.morph``, but see that the difference + Rw has increased substantially due to our smear value. One + approach, as described above, is to remove the ``-a`` from the + above command and run it again. + + * Note: The warnings that the Terminal/Command Prompt + displays are largely numerical in nature and do not + indicate a physically irrelevant guess. These are somewhat + superficial and in most cases can be ignored. + + We see that this has had hardly any effect on our PDF. To see + an effect, we restrict the ``rmin`` and ``rmax`` values to + reflect relevant data range by typing :: + + diffpy.morph --scale=0.8 --smear=0.5 --rmin=1.5 --rmax=30 darkSub_rh20_C_01.gr darkSub_rh20_C_44.gr + + Now, we see that the difference Rw = 0.204 and that the optimized + ``smear=-0.084138``. + + * We restricted the r values because some of the Gaussian + smear effects are only visible in a fixed r range. We + chose this r range by noting where most of our relevant + data was that was not exponentially decayed by + instrumental shortcomings. + + We are getting closer to an acceptably close fit to our data! + + 8. Finally, we will examine the stretch factor. Provide an initial + guess by typing :: + + diffpy.morph --scale=0.8 --smear=-0.08 --stretch=0.5 --rmin=1.5 --rmax=30 -a darkSub_rh20_C_01.gr darkSub_rh20_C_44.gr + + And noting that the difference has increased. Before continuing, + see if you can see which direction (higher or lower) our initial + estimate for the stretch factor needs to go and then removing + the ``-a`` to check optimized value! + + If you cannot, type :: + + diffpy.morph --scale=0.8 --smear=-0.08 --stretch=0.005 --rmin=1.5 --rmax=30 -a darkSub_rh20_C_01.gr darkSub_rh20_C_44.gr + + to observe decreased difference and then remove ``-a`` to see + the optimized ``--stretch=0.001762``. We have now reached + the optimal fit for our PDF! + + .. figure:: images/qs_tutorial_morphed.png + :align: center + :figwidth: 100% + + The optimal fit after applying the scale, smear, and stretch morphs. + + 9. Now, try it on your own! If you have personally collected or + otherwise readily available PDF data, try this process to see if + you can morph your PDFs to one another. Many of the parameters + provided in this tutorial are unique to it, so be cautious about + your choices and made sure that they remain physically relevant. + +Enjoy the software! + +.. Additional diffpy.morph Functionality/Exploration +.. ------------------------------------------------- +.. TODO include undoped PDF example + +Extra Tutorials +=============== +``diffpy.morph`` has some more functionalities not showcased in the basic workflow above +(see `diffpy.morph --help` for an overview of these functionalities). +Tutorials for these additional functionalities are included below. Additional +files for these tutorials can be downloaded +:download:`here <../../tutorial/additionalData.zip>`. + +Performing Multiple Morphs +-------------------------- + +It may be useful to morph a PDF against multiple targets: +for example, you may want to morph a PDF against multiple PDFs measured +at various temperatures to determine whether a phase change has occurred. +``diffpy.morph`` currently allows users to morph a PDF against all files in a +selected directory and plot resulting :math:`R_w` values from each morph. + +1. Within the ``additionalData`` directory, ``cd`` into the + ``morphsequence`` directory. Inside, you will find multiple PDFs of + :math:`SrFe_2As_2` measured at various temperatures. These PDFs are + from `"Atomic Pair Distribution Function Analysis: A primer" + `_. + +2. Let us start by getting the Rw of ``SrFe2As2_150K.gr`` compared to + all other files in the directory. Run :: + + diffpy.morph 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 + ``morphsequence``.:: + + diffpy.morph SrFe2As2_150K.gr . --multiple-targets --sort-by=temperature + +.. figure:: images/ex_tutorial_bar.png + :align: center + :figwidth: 100% + + Bar chart of :math:`R_W` values for each target file. Target files are + listed in ASCII sort order. + +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 :: + + diffpy.morph 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 + `` = `` and are located above + the ``r`` versus ``gr`` table in each PDF file.:: + + # SrFe2As2_150K.gr + [PDF Parameters] + temperature = 150 + wavelength = 0.1 + ... + +.. figure:: images/ex_tutorial_temp.png + :align: center + :figwidth: 100% + + The :math:`R_W` plotted against the temperature the target PDF was + measured at. + +4. Between 192K and 198K, the Rw has a sharp increase, indicating that + we may have a phase change. To confirm, let us now apply morphs + onto `` SrFe2As2_150K.gr`` with all other files in + ``morphsequence`` as targets :: + + diffpy.morph --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. + +5. We should now see a sharper increase in Rw between 192K and 198K. + +6. Go back to the terminal to see optimized morphing parameters from each morph. + +7. On the morph with ``SrFe2As2_192K.gr`` as target, ``scale = + 0.972085`` and ``stretch = 0.000508`` and with ``SrFe2As2_198K.gr`` + as target, ``scale = 0.970276`` and ``stretch = 0.000510``. These + are very similar, meaning that thermal lattice expansion (accounted + for by ``stretch``) is not occurring. This, coupled with the fact + that the Rw significantly increases suggests a phase change in this + temperature regime. (In fact, :math:`SrFe_2As_2` does transition + from orthorhombic at lower temperature to tetragonal at higher + temperature!). More sophisticated analysis can be done with + `PDFgui `_. + +8. Finally, let us save all the morphed PDFs into a directory + named ``saved-morphs``. :: + + diffpy.morph SrFe2As2_150K.gr . --scale=1 --stretch=0 --multiple-targets \ + --sort-by=temperature --plot-parameter=stretch \ + --save=saved-morphs + + Entering the directory with ``cd`` and viewing its contents with + ``ls``, we see a file named ``morph-reference-table.txt`` with data + about the input morph parameters and re- fined output parameters + and a directory named ``morphs`` containing all the morphed + PDFs. See the ``--save-names-file`` option to see how you can set + the names for these saved morphs! + +Nanoparticle Shape Effects +-------------------------- + +A nanoparticle's finite size and shape can affect the shape of its PDF. +We can use ``diffpy.morph`` to morph a bulk material PDF to simulate these shape effects. +Currently, the supported nanoparticle shapes include: spheres and spheroids. + +* Within the ``additionalData`` directory, ``cd`` into the + ``morphShape`` subdirectory. Inside, you will find a sample Ni bulk + material PDF ``Ni_bulk.gr``. This PDF is from `"Atomic Pair + Distribution Function Analysis: + A primer" `_. + There are also multiple ``.cgr`` files with calculated Ni nanoparticle PDFs. + +* Let us apply various shape effect morphs on the bulk material to + reproduce these calculated PDFs. + + * Spherical Shape + 1. The ``Ni_nano_sphere.cgr`` file contains a generated + spherical nanoparticle with unknown radius. First, let us + plot ``Ni_blk.gr`` against ``Ni_nano_sphere.cgr`` :: + + diffpy.morph Ni_bulk.gr Ni_nano_sphere.cgr + + Despite the two being the same material, the Rw is quite large. + To reduce the Rw, we will apply spherical shape effects onto the PDF. + However, in order to do so, we first need the radius of the + spherical nanoparticle. + + 2. To get the radius, we can first observe a plot of + ``Ni_nano_sphere.cgr`` :: + + diffpy.morph Ni_nano_sphere.cgr Ni_nano_sphere.cgr + + 3. Nanoparticles tend to have broader peaks at r-values larger + than the particle size, corresponding to the much weaker + correlations between molecules. On our plot, beyond r=22.5, + peaks are too broad to be visible, indicating our particle + size to be about 22.4. The approximate radius of a sphere + would be half of that, or 11.2.:: + + diffpy.morph Ni_bulk.gr Ni_nano_sphere.cgr --radius=11.2 -a + + + 4. Now, we are ready to perform a morph applying spherical + effects. To do so, we use the ``--radius`` parameter :: + + diffpy.morph Ni_bulk.gr Ni_nano_sphere.cgr --radius=11.2 -a + + 5. We can see that the Rw value has significantly decreased + from before. Run without the ``-a`` tag to refine :: + + diffpy.morph Ni_bulk.gr Ni_nano_sphere.cgr --radius=11.2 + + 6. After refining, we see the actual radius of the + nanoparticle was closer to 12. + + * Spheroidal Shape + + 1. The ``Ni_nano_spheroid.cgr`` file contains a calculated + spheroidal Ni nanoparticle. Again, we can begin by plotting + the bulk material against our nanoparticle :: + + diffpy.morph Ni_bulk.gr Ni_nano_spheroid.cgr + + 2. Inside the ``Ni_nano_spheroid.cgr`` file, we are given that + the equatorial radius is 12 and polar radius is 6. This is + enough information to define our spheroid. To apply + spheroid shape effects onto our bulk, run :: + + diffpy.morph Ni_bulk.gr Ni_nano_spheroid.cgr --radius=12 --pradius=6 -a + + Note that the equatorial radius corresponds to the + ``--radius`` parameter and polar radius to ``--pradius``. + + 3. Remove the ``-a`` tag to refine. + +There is also support for morphing from a nanoparticle to a bulk. When +applying the inverse morphs, it is recommended to set ``--rmax=psize`` +where ``psize`` is the longest diameter of the nanoparticle. + +Bug Reports +=========== + +Please enjoy using our software! If you come across any bugs in the +application, please report them to diffpy-users@googlegroups.com. diff --git a/news/squeeze_cli.rst b/news/squeeze_cli.rst new file mode 100644 index 00000000..5a673f0f --- /dev/null +++ b/news/squeeze_cli.rst @@ -0,0 +1,24 @@ +**Added:** + +* Squeeze morph now added to CLI. + +**Changed:** + +* Stretch disabled when squeeze is above polynomial order 0. +* Horizontal shift morph disabled when squeeze is enabled. + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* diff --git a/src/diffpy/morph/morph_io.py b/src/diffpy/morph/morph_io.py index b12cd3f1..79aeb8c8 100644 --- a/src/diffpy/morph/morph_io.py +++ b/src/diffpy/morph/morph_io.py @@ -67,6 +67,17 @@ def single_morph_output( ) morphs_out = "# Optimized morphing parameters:\n" + # Handle special inputs + if "squeeze" in morph_results: + sq_dict = morph_results.pop("squeeze") + rw_pos = list(morph_results.keys()).index("Rw") + morph_results_list = list(morph_results.items()) + for idx, _ in enumerate(sq_dict): + morph_results_list.insert( + rw_pos + idx, (f"squeeze a{idx}", sq_dict[f"a{idx}"]) + ) + morph_results = dict(morph_results_list) + # Normal inputs morphs_out += "\n".join( f"# {key} = {morph_results[key]:.6f}" for key in morph_results.keys() ) diff --git a/src/diffpy/morph/morphapp.py b/src/diffpy/morph/morphapp.py index ad7ca73c..a0452242 100755 --- a/src/diffpy/morph/morphapp.py +++ b/src/diffpy/morph/morphapp.py @@ -148,26 +148,50 @@ def custom_error(self, msg): action="append", dest="exclude", metavar="MANIP", - help="""Exclude a manipulation from refinement by name. This can - appear multiple times.""", + 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.", + help=( + "Apply scale factor SCALE. " + "This multiplies the function ordinate by SCALE." + ), ) group.add_option( "--stretch", type="float", metavar="STRETCH", - help="Stretch PDF by a fraction STRETCH.", + help=( + "Stretch function grid by a fraction STRETCH. " + "This multiplies the function grid by 1+STRETCH." + ), + ) + group.add_option( + "--squeeze", + metavar="a0,a1,...,an", + help=( + "Squeeze function grid given a polynomial " + "a0+a1*x+a2*x^2+...a_n*x^n." + "n is dependent on the number of values in the " + "user-inputted comma-separated list. " + "When this option is enabled, --hshift is disabled. " + "When n>1, --stretch is disabled. " + "See online documentation for more information." + ), ) group.add_option( "--smear", type="float", metavar="SMEAR", - help="Smear peaks with a Gaussian of width SMEAR.", + help=( + "Smear peaks with a Gaussian of width SMEAR. " + "This convolves the function with a Gaussian of width SMEAR." + ), ) group.add_option( "--slope", @@ -444,6 +468,17 @@ def single_morph(parser, opts, pargs, stdout_flag=True): chain.append(morphs.MorphRGrid()) refpars = [] + # Squeeze + squeeze_poly_deg = -1 + if opts.squeeze is not None: + squeeze_coeffs = opts.squeeze.strip().split(",") + squeeze_dict_in = {} + for idx, coeff in enumerate(squeeze_coeffs): + squeeze_dict_in.update({f"a{idx}": float(coeff)}) + squeeze_poly_deg = len(squeeze_coeffs) - 1 + chain.append(morphs.MorphSqueeze()) + config["squeeze"] = squeeze_dict_in + refpars.append("squeeze") # Scale if opts.scale is not None: scale_in = opts.scale @@ -451,15 +486,19 @@ def single_morph(parser, opts, pargs, stdout_flag=True): config["scale"] = scale_in refpars.append("scale") # Stretch - if opts.stretch is not None: + # Only enable stretch if squeeze is lower than degree 1 + if opts.stretch is not None and squeeze_poly_deg < 1: stretch_in = opts.stretch chain.append(morphs.MorphStretch()) config["stretch"] = stretch_in refpars.append("stretch") # Shift - if opts.hshift is not None or opts.vshift is not None: + # Only enable hshift is squeeze is not enabled + if ( + opts.hshift is not None and squeeze_poly_deg < 0 + ) or opts.vshift is not None: chain.append(morphs.MorphShift()) - if opts.hshift is not None: + if opts.hshift is not None and squeeze_poly_deg < 0: hshift_in = opts.hshift config["hshift"] = hshift_in refpars.append("hshift") @@ -557,6 +596,8 @@ def single_morph(parser, opts, pargs, stdout_flag=True): chain[0] = morphs.Morph() chain(x_morph, y_morph, x_target, y_target) + # FOR FUTURE MAINTAINERS + # Any new morph should have their input morph parameters updated here # Input morph parameters morph_inputs = { "scale": scale_in, @@ -564,6 +605,14 @@ def single_morph(parser, opts, pargs, stdout_flag=True): "smear": smear_in, } morph_inputs.update({"hshift": hshift_in, "vshift": vshift_in}) + # More complex input morph parameters are only displayed conditionally + if opts.squeeze is not None: + squeeze_coeffs = opts.squeeze.strip().split(",") + squeeze_dict = {} + for idx, coeff in enumerate(squeeze_coeffs): + squeeze_dict.update({f"a{idx}": float(coeff)}) + for idx, _ in enumerate(squeeze_dict): + morph_inputs.update({f"squeeze a{idx}": squeeze_dict[f"a{idx}"]}) # Output morph parameters morph_results = dict(config.items()) diff --git a/tests/test_morphio.py b/tests/test_morphio.py index 5b85c12a..0bfc9fd0 100644 --- a/tests/test_morphio.py +++ b/tests/test_morphio.py @@ -2,6 +2,7 @@ from pathlib import Path +import numpy as np import pytest from diffpy.morph.morphapp import ( @@ -27,6 +28,27 @@ tssf = testdata_dir.joinpath("testsequence_serialfile.json") +# Ignore PATH data when comparing files +def ignore_path(line): + # Lines containing FILE PATH data begin with '# from ' + if "# from " in line: + return False + # Lines containing DIRECTORY PATH data begin with '# with ' + if "# with " in line: + return False + return True + + +def isfloat(s): + """True if s is convertible to float.""" + try: + float(s) + return True + except ValueError: + pass + return False + + class TestApp: @pytest.fixture def setup(self): @@ -46,16 +68,6 @@ def setup(self): return def test_morph_outputs(self, setup, tmp_path): - # Ignore PATH data when comparing files - def ignore_path(line): - # Lines containing FILE PATH data begin with '# from ' - if "# from " in line: - return False - # Lines containing DIRECTORY PATH data begin with '# with ' - if "# with " in line: - return False - return True - morph_file = self.testfiles[0] target_file = self.testfiles[-1] @@ -137,3 +149,46 @@ def ignore_path(line): generated = filter(ignore_path, gf) target = filter(ignore_path, tf) assert all(x == y for x, y in zip(generated, target)) + + def test_morph_squeeze_outputs(self, setup, tmp_path): + # The file squeeze_morph has a squeeze and stretch applied + morph_file = testdata_dir / "squeeze_morph.cgr" + target_file = testdata_dir / "squeeze_target.cgr" + sqr = tmp_path / "squeeze_morph_result.cgr" + sqr_name = sqr.resolve().as_posix() + # Note that stretch and hshift should not be considered + (opts, _) = self.parser.parse_args( + [ + "--scale", + "2", + "--squeeze", + "0,-0.001,-0.0001,0.0001", + "--stretch", + "1", + "--hshift", + "1", + "-s", + sqr_name, + "-n", + "--verbose", + ] + ) + pargs = [morph_file, target_file] + single_morph(self.parser, opts, pargs, stdout_flag=False) + + # Check squeeze morph generates the correct output + with open(sqr) as mf: + with open(target_file) as tf: + morphed = filter(ignore_path, mf) + target = filter(ignore_path, tf) + for m, t in zip(morphed, target): + m_row = m.split() + t_row = t.split() + assert len(m_row) == len(t_row) + for idx, _ in enumerate(m_row): + if isfloat(m_row[idx]) and isfloat(t_row[idx]): + assert np.isclose( + float(m_row[idx]), float(t_row[idx]) + ) + else: + assert m_row[idx] == t_row[idx] diff --git a/tests/testdata/squeeze_morph.cgr b/tests/testdata/squeeze_morph.cgr new file mode 100644 index 00000000..cc7799b9 --- /dev/null +++ b/tests/testdata/squeeze_morph.cgr @@ -0,0 +1,105 @@ +# PDF created by diffpy.morph +# from PATH + +# Labels: [r] [gr] +0.000000000000000000e+00 0.000000000000000000e+00 +1.000000000000000056e-01 2.016607210740701817e-01 +2.000000000000000111e-01 4.012816425967311584e-01 +3.000000000000000444e-01 5.968384836782407721e-01 +4.000000000000000222e-01 7.863460390718853832e-01 +5.000000000000000000e-01 9.678774221035963965e-01 +6.000000000000000888e-01 1.139582805695501078e+00 +7.000000000000000666e-01 1.299707497430252046e+00 +8.000000000000000444e-01 1.446609189174991705e+00 +9.000000000000000222e-01 1.578774227495413296e+00 +1.000000000000000000e+00 1.694832757920656352e+00 +1.100000000000000089e+00 1.793572604043012886e+00 +1.200000000000000178e+00 1.873951751421987222e+00 +1.300000000000000044e+00 1.935109316274401969e+00 +1.400000000000000133e+00 1.976374889929940482e+00 +1.500000000000000000e+00 1.997276161968231323e+00 +1.600000000000000089e+00 1.997544737777092294e+00 +1.700000000000000178e+00 1.977120079923743390e+00 +1.800000000000000044e+00 1.936151517147448820e+00 +1.900000000000000133e+00 1.874998279892714503e+00 +2.000000000000000000e+00 1.794227537029879693e+00 +2.100000000000000089e+00 1.694610424671280313e+00 +2.200000000000000178e+00 1.577116074695904757e+00 +2.300000000000000266e+00 1.442903667646756372e+00 +2.400000000000000355e+00 1.293312551959283851e+00 +2.500000000000000000e+00 1.129850488905959738e+00 +2.600000000000000089e+00 9.541801000842509151e-01 +2.700000000000000178e+00 7.681036116097271771e-01 +2.800000000000000266e+00 5.735460062730138864e-01 +2.900000000000000355e+00 3.725367116437122150e-01 +3.000000000000000000e+00 1.671899683154590699e-01 +3.100000000000000089e+00 -4.031596196150075834e-02 +3.200000000000000178e+00 -2.477605737698468646e-01 +3.300000000000000266e+00 -4.529036928636547832e-01 +3.400000000000000355e+00 -6.535086474160737291e-01 +3.500000000000000000e+00 -8.473658233427887598e-01 +3.600000000000000089e+00 -1.032316381403495242e+00 +3.700000000000000178e+00 -1.206275905404040172e+00 +3.800000000000000266e+00 -1.367257744179736667e+00 +3.900000000000000355e+00 -1.513395805283929141e+00 +4.000000000000000000e+00 -1.642966555577477061e+00 +4.100000000000000533e+00 -1.754409983348725222e+00 +4.200000000000000178e+00 -1.846349278313989206e+00 +4.299999999999999822e+00 -1.917608989968017763e+00 +4.400000000000000355e+00 -1.967231431369953931e+00 +4.500000000000000000e+00 -1.994491104644685819e+00 +4.600000000000000533e+00 -1.998906936314116090e+00 +4.700000000000000178e+00 -1.980252125089067672e+00 +4.800000000000000711e+00 -1.938561421967258891e+00 +4.900000000000000355e+00 -1.874135682387076951e+00 +5.000000000000000000e+00 -1.787543552743151798e+00 +5.100000000000000533e+00 -1.679620178709657630e+00 +5.200000000000000178e+00 -1.551462850439542906e+00 +5.300000000000000711e+00 -1.404423529676374072e+00 +5.400000000000000355e+00 -1.240098235957646233e+00 +5.500000000000000000e+00 -1.060313303193321621e+00 +5.600000000000000533e+00 -8.671085537216786099e-01 +5.700000000000000178e+00 -6.627174741864847451e-01 +5.800000000000000711e+00 -4.495445159157776538e-01 +5.900000000000000355e+00 -2.301396815438895571e-01 +6.000000000000000000e+00 -7.170598996826864358e-03 +6.100000000000000533e+00 2.166076767888532317e-01 +6.200000000000000178e+00 4.383848554024750710e-01 +6.300000000000000711e+00 6.553292792208245121e-01 +6.400000000000000355e+00 8.646231160092439083e-01 +6.500000000000000000e+00 1.063498489850685624e+00 +6.600000000000000533e+00 1.249274133578965218e+00 +6.700000000000000178e+00 1.419392118491213939e+00 +6.800000000000000711e+00 1.571454193726408821e+00 +6.900000000000000355e+00 1.703257248921869360e+00 +7.000000000000000000e+00 1.812827400185563764e+00 +7.100000000000000533e+00 1.898452191616431639e+00 +7.200000000000000178e+00 1.958710403102522868e+00 +7.300000000000000711e+00 1.992498960420514109e+00 +7.400000000000000355e+00 1.999056456187634501e+00 +7.500000000000000000e+00 1.977982810349711684e+00 +7.600000000000000533e+00 1.929254626918742277e+00 +7.700000000000000178e+00 1.853235839800372542e+00 +7.800000000000000711e+00 1.750683284871877854e+00 +7.900000000000000355e+00 1.622746887964007678e+00 +8.000000000000000000e+00 1.470964218916802180e+00 +8.099999999999999645e+00 1.297249230133007636e+00 +8.200000000000001066e+00 1.103875073606781942e+00 +8.300000000000000711e+00 8.934509726687409614e-01 +8.400000000000000355e+00 6.688932129054430131e-01 +8.500000000000000000e+00 4.333904099623434036e-01 +8.599999999999999645e+00 1.903633091336342231e-01 +8.700000000000001066e+00 -5.658052847403799435e-02 +8.800000000000000711e+00 -3.036966972619735139e-01 +8.900000000000000355e+00 -5.471580191460774234e-01 +9.000000000000000000e+00 -7.831120606064566614e-01 +9.099999999999999645e+00 -1.007741344138793016e+00 +9.200000000000001066e+00 -1.217325414256249960e+00 +9.300000000000000711e+00 -1.408303836788730168e+00 +9.400000000000000355e+00 -1.577339138701817634e+00 +9.500000000000000000e+00 -1.721378636094831327e+00 +9.600000000000001421e+00 -1.837714052498993222e+00 +9.700000000000001066e+00 -1.924037800077388338e+00 +9.800000000000000711e+00 -1.978494784713575205e+00 +9.900000000000000355e+00 -1.999728603987454667e+00 +1.000000000000000000e+01 -1.986921036185803846e+00 diff --git a/tests/testdata/squeeze_target.cgr b/tests/testdata/squeeze_target.cgr new file mode 100644 index 00000000..5a7c4017 --- /dev/null +++ b/tests/testdata/squeeze_target.cgr @@ -0,0 +1,128 @@ +# PDF created by diffpy.morph +# from PATH + +# Input morphing parameters: +# scale = 2.0 +# stretch = None +# smear = None +# hshift = None +# vshift = None +# squeeze a0 = 0.0 +# squeeze a1 = -0.001 +# squeeze a2 = -0.0001 +# squeeze a3 = 0.0001 + +# Optimized morphing parameters: +# rmin = 0.000000 +# rmax = 10.100000 +# rstep = 0.100000 +# scale = 0.500000 +# squeeze a0 = 0.000000 +# squeeze a1 = 0.010000 +# squeeze a2 = 0.000100 +# squeeze a3 = 0.001000 +# Rw = 0.000000 +# Pearson = 1.000000 + +# Labels: [r] [gr] +0.000000000000000000e+00 -8.357788796904224253e-08 +1.000000000000000056e-01 9.983335989539958433e-02 +2.000000000000000111e-01 1.986692882755068390e-01 +3.000000000000000444e-01 2.955201900777184587e-01 +4.000000000000000222e-01 3.894183455897525792e-01 +5.000000000000000000e-01 4.794255628338816577e-01 +6.000000000000000888e-01 5.646425163401342928e-01 +7.000000000000000666e-01 6.442177472575285613e-01 +8.000000000000000444e-01 7.173561656390742280e-01 +9.000000000000000222e-01 7.833269965082827468e-01 +1.000000000000000000e+00 8.414710809423141535e-01 +1.100000000000000089e+00 8.912074623687431529e-01 +1.200000000000000178e+00 9.320391912438557025e-01 +1.300000000000000044e+00 9.635582904389520253e-01 +1.400000000000000133e+00 9.854498316195489105e-01 +1.500000000000000000e+00 9.974950819180453676e-01 +1.600000000000000089e+00 9.995736894484723578e-01 +1.700000000000000178e+00 9.916648858278295231e-01 +1.800000000000000044e+00 9.738476936863433853e-01 +1.900000000000000133e+00 9.463001370918723287e-01 +2.000000000000000000e+00 9.092974627759751183e-01 +2.100000000000000089e+00 8.632093899332391462e-01 +2.200000000000000178e+00 8.084964160720563564e-01 +2.300000000000000266e+00 7.457052158273517195e-01 +2.400000000000000355e+00 6.754631787095541906e-01 +2.500000000000000000e+00 5.984721403688244568e-01 +2.600000000000000089e+00 5.155013700132252685e-01 +2.700000000000000178e+00 4.273798840535988908e-01 +2.800000000000000266e+00 3.349881627820611163e-01 +2.900000000000000355e+00 2.392493528578337192e-01 +3.000000000000000000e+00 1.411200435139138010e-01 +3.100000000000000089e+00 4.158070865920206888e-02 +3.200000000000000178e+00 -5.837408960958168080e-02 +3.300000000000000266e+00 -1.577456381872548441e-01 +3.400000000000000355e+00 -2.555410515265202354e-01 +3.500000000000000000e+00 -3.507831918753864797e-01 +3.600000000000000089e+00 -4.425204320563480009e-01 +3.700000000000000178e+00 -5.298361632374190000e-01 +3.800000000000000266e+00 -6.118579527020228115e-01 +3.900000000000000355e+00 -6.877662601339329385e-01 +4.000000000000000000e+00 -7.568026253602615494e-01 +4.100000000000000533e+00 -8.182772483416952403e-01 +4.200000000000000178e+00 -8.715758921842486906e-01 +4.299999999999999822e+00 -9.161660173828498621e-01 +4.400000000000000355e+00 -9.516021002227514902e-01 +4.500000000000000000e+00 -9.775300836040233809e-01 +4.600000000000000533e+00 -9.936909136186475866e-01 +4.700000000000000178e+00 -9.999231265841722616e-01 +4.800000000000000711e+00 -9.961644607670143703e-01 +4.900000000000000355e+00 -9.824524768209257353e-01 +5.000000000000000000e+00 -9.589241809225684809e-01 +5.100000000000000533e+00 -9.258146546047605341e-01 +5.200000000000000178e+00 -8.834547052655963295e-01 +5.300000000000000711e+00 -8.322675611647437632e-01 +5.400000000000000355e+00 -7.727646443038580504e-01 +5.500000000000000000e+00 -7.055404651441096187e-01 +5.600000000000000533e+00 -6.312667151091209128e-01 +5.700000000000000178e+00 -5.506855493720435035e-01 +5.800000000000000711e+00 -4.646021351237333841e-01 +5.900000000000000355e+00 -3.738766024924461973e-01 +6.000000000000000000e+00 -2.794154497218503952e-01 +6.100000000000000533e+00 -1.821624876417017036e-01 +6.200000000000000178e+00 -8.308941446470229086e-02 +6.300000000000000711e+00 1.681388447947275780e-02 +6.400000000000000355e+00 1.165492148948801265e-01 +6.500000000000000000e+00 2.151200311503978224e-01 +6.600000000000000533e+00 3.115414025443001833e-01 +6.700000000000000178e+00 4.048499089995918898e-01 +6.800000000000000711e+00 4.941132660497548068e-01 +6.900000000000000355e+00 5.784396255563073463e-01 +7.000000000000000000e+00 6.569864681520779515e-01 +7.100000000000000533e+00 7.289689982084295305e-01 +7.200000000000000178e+00 7.936679588809117947e-01 +7.300000000000000711e+00 8.504367914640226234e-01 +7.400000000000000355e+00 8.987081693992005071e-01 +7.500000000000000000e+00 9.379998675576307621e-01 +7.600000000000000533e+00 9.679194196440626952e-01 +7.700000000000000178e+00 9.881679699685518292e-01 +7.800000000000000711e+00 9.985432236313553922e-01 +7.900000000000000355e+00 9.989414376611046587e-01 +8.000000000000000000e+00 9.893584389332742424e-01 +8.099999999999999645e+00 9.698898327615692594e-01 +8.200000000000001066e+00 9.407303515736493704e-01 +8.300000000000000711e+00 9.021715336418995035e-01 +8.400000000000000355e+00 8.545987062144498880e-01 +8.500000000000000000e+00 7.984871238128524729e-01 +8.599999999999999645e+00 7.343972374542593329e-01 +8.700000000000001066e+00 6.629692383579551818e-01 +8.800000000000000711e+00 5.849170287654014144e-01 +8.900000000000000355e+00 5.010206616413290792e-01 +9.000000000000000000e+00 4.121183976640565572e-01 +9.099999999999999645e+00 3.190983923437636927e-01 +9.200000000000001066e+00 2.228899358017164267e-01 +9.300000000000000711e+00 1.244543754116841927e-01 +9.400000000000000355e+00 2.477539551689142416e-02 +9.500000000000000000e+00 -7.515108859995893453e-02 +9.600000000000001421e+00 -1.743267637418187965e-01 +9.700000000000001066e+00 -2.717606916786979854e-01 +9.800000000000000711e+00 -3.664791265996873437e-01 +9.900000000000000355e+00 -4.575357200218788112e-01 +1.000000000000000000e+01 -5.440208946101240395e-01