Esempio n. 1
0
def makeRecipe(molecule, datname):
    """Create a recipe that uses the DebyePDFGenerator."""

    ## The Profile
    profile = Profile()

    # Load data and add it to the profile
    profile.loadtxt(datname)
    profile.setCalculationRange(xmin=1.2, xmax=8)

    ## The ProfileGenerator
    # Create a DebyePDFGenerator named "G".
    generator = DebyePDFGenerator("G")
    generator.setStructure(molecule)
    # These are metadata needed by the generator
    generator.setQmin(0.68)
    generator.setQmax(22)

    ## The FitContribution
    contribution = FitContribution("bucky")
    contribution.addProfileGenerator(generator)
    contribution.setProfile(profile, xname="r")

    # Make a FitRecipe.
    recipe = FitRecipe()
    recipe.addContribution(contribution)

    # Specify which parameters we want to refine.
    c60 = generator.phase

    # We're not going to refine the ADPs. However, every atom must have a
    # small, but finite ADP for the PDF calculator to work properly.
    atoms = c60.getScatterers()
    for atom in atoms:
        atom.Uiso.value = 0.001

    # Scale factor. We cannot optimize this efficiently, so we take the value
    # from a previous refinement. In general, care must be taken to properly
    # determine the scale of the profile, or to make sure that the residual is
    # not affected by the scale.
    generator.scale.value = 1.24457360e+4

    # Allow every atom to move.  We define the bounds to be a window of radius
    # 0.1 centered on the current value of the position.
    win = 0.1
    for idx, atom in enumerate(atoms):
        xname, yname, zname = getXYZNames(idx)
        recipe.addVar(atom.x, name=xname).boundWindow(win)
        recipe.addVar(atom.y, name=yname).boundWindow(win)
        recipe.addVar(atom.z, name=zname).boundWindow(win)

    return recipe
Esempio n. 2
0
def makeRecipe(molecule, datname):
    """Create a recipe that uses the DebyePDFGenerator."""

    ## The Profile
    profile = Profile()

    # Load data and add it to the profile
    profile.loadtxt(datname)
    profile.setCalculationRange(xmin=1.2, xmax=8)

    ## The ProfileGenerator
    # Create a DebyePDFGenerator named "G".
    generator = DebyePDFGenerator("G")
    generator.setStructure(molecule)
    # These are metadata needed by the generator
    generator.setQmin(0.68)
    generator.setQmax(22)

    ## The FitContribution
    contribution = FitContribution("bucky")
    contribution.addProfileGenerator(generator)
    contribution.setProfile(profile, xname = "r")

    # Make a FitRecipe.
    recipe = FitRecipe()
    recipe.addContribution(contribution)

    # Specify which parameters we want to refine.
    c60 = generator.phase

    # We're not going to refine the ADPs. However, every atom must have a
    # small, but finite ADP for the PDF calculator to work properly.
    atoms = c60.getScatterers()
    for atom in atoms:
        atom.Uiso.value = 0.001

    # Scale factor. We cannot optimize this efficiently, so we take the value
    # from a previous refinement. In general, care must be taken to properly
    # determine the scale of the profile, or to make sure that the residual is
    # not affected by the scale.
    generator.scale.value = 1.24457360e+4

    # Allow every atom to move.  We define the bounds to be a window of radius
    # 0.1 centered on the current value of the position.
    win = 0.1
    for idx, atom in enumerate(atoms):
        xname, yname, zname = getXYZNames(idx)
        recipe.addVar(atom.x, name = xname).boundWindow(win)
        recipe.addVar(atom.y, name = yname).boundWindow(win)
        recipe.addVar(atom.z, name = zname).boundWindow(win)

    return recipe
Esempio n. 3
0
    def addPhase(self, name, parset, periodic=True):
        """Add a phase that goes into the PDF calculation.

        name    --  A name to give the generator that will manage the PDF
                    calculation from the passed parameter phase. The parset
                    will be accessible via the name "phase" as an attribute
                    of the generator, e.g., contribution.name.phase, where
                    'contribution' is this contribution and 'name' is passed
                    name.
        parset  --  A SrRealParSet that holds the structural information.
                    This can be used to share the phase between multiple
                    BasePDFGenerators, and have the changes in one reflect in
                    another.
        periodic -- The structure should be treated as periodic.  If this is
                    True (default), then a PDFGenerator will be used to
                    calculate the PDF from the phase. Otherwise, a
                    DebyePDFGenerator will be used. Note that some structures
                    do not support periodicity, in which case this may be
                    ignored.

        Returns the new phase (ParameterSet appropriate for what was passed in
        stru.)

        """
        # Based on periodic, create the proper generator.
        if periodic:
            from diffpy.srfit.pdf.pdfgenerator import PDFGenerator
            gen = PDFGenerator(name)
        else:
            from diffpy.srfit.pdf.debyepdfgenerator import DebyePDFGenerator
            gen = DebyePDFGenerator(name)

        # Set up the generator
        gen.setPhase(parset, periodic)
        self._setupGenerator(gen)

        return gen.phase
Esempio n. 4
0
    def addStructure(self, name, stru, periodic=True):
        """Add a phase that goes into the PDF calculation.

        name    --  A name to give the generator that will manage the PDF
                    calculation from the passed structure. The adapted
                    structure will be accessible via the name "phase" as an
                    attribute of the generator, e.g.
                    contribution.name.phase, where 'contribution' is this
                    contribution and 'name' is passed name.
                    (default), then the name will be set as "phase".
        stru    --  diffpy.Structure.Structure, pyobjcryst.crystal.Crystal or
                    pyobjcryst.molecule.Molecule instance.  Default None.
        periodic -- The structure should be treated as periodic.  If this is
                    True (default), then a PDFGenerator will be used to
                    calculate the PDF from the phase. Otherwise, a
                    DebyePDFGenerator will be used. Note that some structures
                    do not support periodicity, in which case this may be
                    ignored.

        Returns the new phase (ParameterSet appropriate for what was passed in
        stru.)

        """
        # Based on periodic, create the proper generator.
        if periodic:
            from diffpy.srfit.pdf.pdfgenerator import PDFGenerator
            gen = PDFGenerator(name)
        else:
            from diffpy.srfit.pdf.debyepdfgenerator import DebyePDFGenerator
            gen = DebyePDFGenerator(name)

        # Set up the generator
        gen.setStructure(stru, "phase", periodic)
        self._setupGenerator(gen)

        return gen.phase
Esempio n. 5
0
def makeRecipe(molecule, datname):
    """Create a recipe that uses the DebyePDFGenerator."""

    ## The Profile
    profile = Profile()

    # Load data and add it to the profile
    profile.loadtxt(datname)
    profile.setCalculationRange(xmin=1.2, xmax=8)

    ## The ProfileGenerator
    # Create a DebyePDFGenerator named "G".
    generator = DebyePDFGenerator("G")
    generator.setStructure(molecule)
    # These are metadata needed by the generator
    generator.setQmin(0.68)
    generator.setQmax(22)

    ## The FitContribution
    contribution = FitContribution("bucky")
    contribution.addProfileGenerator(generator)
    contribution.setProfile(profile, xname = "r")

    # Make a FitRecipe.
    recipe = FitRecipe()
    recipe.addContribution(contribution)

    # Specify which parameters we want to refine. We'll be using the
    # MoleculeParSet within the generator, so let's get a handle to it. See the
    # diffpy.srfit.structure.objcryststructure module for more information
    # about the MoleculeParSet hierarchy.
    c60 = generator.phase

    # First, the isotropic thermal displacement factor.
    Biso = recipe.newVar("Biso")
    for atom in c60.getScatterers():

        # We have defined a 'center' atom that is a dummy, which means that it
        # has no scattering power. It is only used as a reference point for
        # our bond length. We don't want to constrain it.
        if not atom.isDummy():
            recipe.constrain(atom.Biso, Biso)

    # We need to let the molecule expand. If we were modeling it as a crystal,
    # we could let the unit cell expand. For instruction purposes, we use a
    # Molecule to model C60, and molecules have different modeling options than
    # crystals. To make the molecule expand from a central point, we will
    # constrain the distance from each atom to a dummy center atom that was
    # created with the molecule, and allow that distance to vary. (We could
    # also let the nearest-neighbor bond lengths vary, but that would be much
    # more difficult to set up.)
    center = c60.center
    # Create a new Parameter that represents the radius of the molecule. Note
    # that we don't give it an initial value. Since the variable is being
    # directly constrained to further below, its initial value will be inferred
    # from the constraint.
    radius = recipe.newVar("radius")
    for i, atom in enumerate(c60.getScatterers()):

        if atom.isDummy():
            continue

        # This creates a Parameter that moves the second atom according to the
        # bond length. Note that each Parameter needs a unique name.
        par = c60.addBondLengthParameter("rad%i"%i, center, atom)
        recipe.constrain(par, radius)

    # Add the correlation term, scale. The scale is too short to effectively
    # determine qdamp.
    recipe.addVar(generator.delta2, 2)
    recipe.addVar(generator.scale, 1.3e4)

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