simplepdftwophase.pyΒΆ

#!/usr/bin/env python
########################################################################
#
# diffpy.srfit      by DANSE Diffraction group
#                   Simon J. L. Billinge
#                   (c) 2010 The Trustees of Columbia University
#                   in the City of New York.  All rights reserved.
#
# File coded by:    Chris Farrow
#
# See AUTHORS.txt for a list of people who contributed.
# See LICENSE_DANSE.txt for license information.
#
########################################################################

"""Example of a simplified PDF refinement of two-phase structure."""

from pyobjcryst import loadCrystal

from diffpy.srfit.pdf import PDFContribution
from diffpy.srfit.fitbase import FitRecipe, FitResults

from gaussianrecipe import scipyOptimize
from crystalpdftwophase import plotResults

####### Example Code

def makeRecipe(niciffile, siciffile, datname):
    """Create a fitting recipe for crystalline PDF data."""

    # Load data and add it to the profile
    contribution = PDFContribution("nisi")
    contribution.loadData(datname)
    contribution.setCalculationRange(xmax = 20)

    stru = loadCrystal(niciffile)
    contribution.addStructure("ni", stru)

    stru = loadCrystal(siciffile)
    contribution.addStructure("si", stru)

    # Make the FitRecipe and add the FitContribution.
    recipe = FitRecipe()
    recipe.addContribution(contribution)

    ## Configure the fit variables
    # Start by configuring the scale factor and resolution factors.
    # We want the sum of the phase scale factors to be 1.
    recipe.newVar("scale_ni", 0.1)
    recipe.constrain(contribution.ni.scale, "scale_ni")
    recipe.constrain(contribution.si.scale, "1 - scale_ni")
    # We also want the resolution factor to be the same on each. This is done
    # for free by the PDFContribution. We simply need to add it to the recipe.
    recipe.addVar(contribution.qdamp, 0.03)

    # Vary the gloabal scale as well.
    recipe.addVar(contribution.scale, 1)

    # Now we can configure the structural parameters. Since we're using
    # ObjCrystCrystalParSets, the space group constraints are automatically
    # applied to each phase. We must selectively vary the free parameters.
    #
    # First the nickel parameters.
    # Note that ni is the name of the PDFGenerator that was automatically
    # created by the PDFContribution. We selected this name in addStructure
    # above.
    phase_ni = contribution.ni.phase
    for par in phase_ni.sgpars:
        recipe.addVar(par, name = par.name + "_ni")
    recipe.addVar(contribution.ni.delta2, name = "delta2_ni")
    # Next the silicon parameters
    phase_si = contribution.si.phase
    for par in phase_si.sgpars:
        recipe.addVar(par, name = par.name + "_si")
    recipe.addVar(contribution.si.delta2, name = "delta2_si")

    # We have prior information from the earlier examples so we'll use it here
    # in the form of restraints.
    #
    # The nickel lattice parameter was measured to be 3.527. The uncertainty
    # values are invalid for that measurement, since the data from which it is
    # derived has no uncertainty. Thus, we will tell the recipe to scale the
    # residual, which means that it will be weighted as much as the average
    # data point during the fit.
    recipe.restrain("a_ni", lb = 3.527, ub = 3.527, scaled = True)
    # Now we do the same with the delta2 and Biso parameters (remember that
    # Biso = 8*pi**2*Uiso)
    recipe.restrain("delta2_ni", lb = 2.22, ub = 2.22, scaled = True)
    recipe.restrain("Biso_0_ni", lb = 0.454, ub = 0.454, scaled = True)
    #
    # We can do the same with the silicon values. We haven't done a thorough
    # job of measuring the uncertainties in the results, so we'll scale these
    # as well.
    recipe.restrain("a_si", lb = 5.430, ub = 5.430, scaled = True)
    recipe.restrain("delta2_si", lb = 3.54, ub = 3.54, scaled = True)
    recipe.restrain("Biso_0_si", lb = 0.645, ub = 0.645, scaled = True)

    # Give the recipe away so it can be used!
    return recipe


if __name__ == "__main__":

    # Make the data and the recipe
    niciffile = "data/ni.cif"
    siciffile = "data/si.cif"
    data = "data/si90ni10-q27r60-xray.gr"

    # Make the recipe
    recipe = makeRecipe(niciffile, siciffile, data)

    # Optimize
    scipyOptimize(recipe)

    # Generate and print the FitResults
    res = FitResults(recipe)
    res.printResults()

    # Plot!
    plotResults(recipe)

# End of file