Source code for diffpy.srfit.structure.diffpyparset

#!/usr/bin/env python
##############################################################################
#
# diffpy.srfit      by DANSE Diffraction group
#                   Simon J. L. Billinge
#                   (c) 2009 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.
#
##############################################################################
"""Adapters for interfacing a diffpy.structure.Structure with SrFit.

A diffpy.structure.Structure object is meant to be passed to a
DiffpyStructureParSet object from this module, which can then be used as a
ParameterSet. (It has other methods for interfacing with SrReal calculator
adapters.) Any change to the lattice or existing atoms will be registered with
the Structure. Changes in the number of atoms will not be recognized.  Thus,
the diffpy.structure.Structure object should be fully configured before passing
it to DiffpyStructureParSet.

DiffpyStructureParSet --  Adapter for diffpy.structure.Structure
DiffpyLatticeParSet   --  Adapter for diffpy.structure.Lattice
DiffpyAtomParSet      --  Adapter for diffpy.structure.Atom
"""

__all__ = ["DiffpyStructureParSet"]

from diffpy.srfit.fitbase.parameter import ParameterAdapter, ParameterProxy
from diffpy.srfit.fitbase.parameterset import ParameterSet
from diffpy.srfit.structure.srrealparset import SrRealParSet
from diffpy.srfit.util.argbinders import bind2nd


# Accessor for xyz of atoms
class _xyzgetter(object):

    def __init__(self, i):
        self.i = i

    def __call__(self, atom):
        return atom.xyz[self.i]


class _xyzsetter(object):

    def __init__(self, i):
        self.i = i

    def __call__(self, atom, value):
        atom.xyz[self.i] = value


class DiffpyAtomParSet(ParameterSet):
    """A wrapper for diffpy.structure.Atom.

    This class derives from diffpy.srfit.fitbase.parameterset.ParameterSet. See
    this class for base attributes.

    Attributes
    ----------
    atom
        The diffpy.structure.Atom this is adapting
    element
        The element name (property).

    Managed Parameters
    ------------------
    occupancy
        Occupancy of the atom on its crystal location
        (ParameterAdapter)
    occ
        Proxy for occupancy (ParameterProxy).
        U11, U22, U33, U12, U21, U23, U32, U13, U31
        --  Anisotropic displacement factor for atom (ParameterAdapter
        or ParameterProxy). Note that the Uij and Uji parameters
        are the same.
    Uiso
        Isotropic ADP (ParameterAdapter).
        B11, B22, B33, B12, B21, B23, B32, B13, B31
        --  Anisotropic displacement factor for atom (ParameterAdapter
        or ParameterProxy). Note that the Bij and Bji parameters
        are the same. (Bij = 8*pi**2*Uij)
    Biso
        Isotropic ADP (ParameterAdapter).
    """

    def __init__(self, name, atom):
        """Initialize.

        Attributes
        ----------
        atom
            A diffpy.structure.Atom instance
        """
        ParameterSet.__init__(self, name)
        self.atom = atom
        a = atom
        # x, y, z, occupancy
        self.addParameter(
            ParameterAdapter("x", a, _xyzgetter(0), _xyzsetter(0))
        )
        self.addParameter(
            ParameterAdapter("y", a, _xyzgetter(1), _xyzsetter(1))
        )
        self.addParameter(
            ParameterAdapter("z", a, _xyzgetter(2), _xyzsetter(2))
        )
        occupancy = ParameterAdapter("occupancy", a, attr="occupancy")
        self.addParameter(occupancy)
        self.addParameter(ParameterProxy("occ", occupancy))
        # U
        self.addParameter(ParameterAdapter("U11", a, attr="U11"))
        self.addParameter(ParameterAdapter("U22", a, attr="U22"))
        self.addParameter(ParameterAdapter("U33", a, attr="U33"))
        U12 = ParameterAdapter("U12", a, attr="U12")
        U21 = ParameterProxy("U21", U12)
        U13 = ParameterAdapter("U13", a, attr="U13")
        U31 = ParameterProxy("U31", U13)
        U23 = ParameterAdapter("U23", a, attr="U23")
        U32 = ParameterProxy("U32", U23)
        self.addParameter(U12)
        self.addParameter(U21)
        self.addParameter(U13)
        self.addParameter(U31)
        self.addParameter(U23)
        self.addParameter(U32)
        self.addParameter(ParameterAdapter("Uiso", a, attr="Uisoequiv"))
        # B
        self.addParameter(ParameterAdapter("B11", a, attr="B11"))
        self.addParameter(ParameterAdapter("B22", a, attr="B22"))
        self.addParameter(ParameterAdapter("B33", a, attr="B33"))
        B12 = ParameterAdapter("B12", a, attr="B12")
        B21 = ParameterProxy("B21", B12)
        B13 = ParameterAdapter("B13", a, attr="B13")
        B31 = ParameterProxy("B31", B13)
        B23 = ParameterAdapter("B23", a, attr="B23")
        B32 = ParameterProxy("B32", B23)
        self.addParameter(B12)
        self.addParameter(B21)
        self.addParameter(B13)
        self.addParameter(B31)
        self.addParameter(B23)
        self.addParameter(B32)
        self.addParameter(ParameterAdapter("Biso", a, attr="Bisoequiv"))
        return

    def __repr__(self):
        return repr(self.atom)

    def _getElem(self):
        return self.atom.element

    def _setElem(self, el):
        self.atom.element = el

    element = property(_getElem, _setElem, "type of atom")


# End class DiffpyAtomParSet


def _latgetter(par):
    return bind2nd(getattr, par)


def _latsetter(par):
    return bind2nd(setattr, par)


class DiffpyLatticeParSet(ParameterSet):
    """A wrapper for diffpy.structure.Lattice.

    This class derives from diffpy.srfit.fitbase.parameterset.ParameterSet.
    See this class for base attributes.

    Attributes
    ----------
    lattice
        The diffpy.structure.Lattice this is adapting
    name
        Always "lattice"
    angunits
        "deg", the units of angle

    Parameters
    ----------
    a
        Unit cell parameters (ParameterAdapter).
    b
        Unit cell parameters (ParameterAdapter).
    c
        Unit cell parameters (ParameterAdapter).
    alpha
        Unit cell parameters (ParameterAdapter).
    beta
        Unit cell parameters (ParameterAdapter).
    gamma
        Unit cell parameters (ParameterAdapter).
    """

    def __init__(self, lattice):
        """Initialize.

        Attributes
        ----------
        lattice
            A diffpy.structure.Lattice instance
        """
        ParameterSet.__init__(self, "lattice")
        self.angunits = "deg"
        self.lattice = lattice
        lat = lattice
        self.addParameter(
            ParameterAdapter("a", lat, _latgetter("a"), _latsetter("a"))
        )
        self.addParameter(
            ParameterAdapter("b", lat, _latgetter("b"), _latsetter("b"))
        )
        self.addParameter(
            ParameterAdapter("c", lat, _latgetter("c"), _latsetter("c"))
        )
        self.addParameter(
            ParameterAdapter(
                "alpha", lat, _latgetter("alpha"), _latsetter("alpha")
            )
        )
        self.addParameter(
            ParameterAdapter(
                "beta", lat, _latgetter("beta"), _latsetter("beta")
            )
        )
        self.addParameter(
            ParameterAdapter(
                "gamma", lat, _latgetter("gamma"), _latsetter("gamma")
            )
        )
        return

    def __repr__(self):
        return repr(self.lattice)


# End class DiffpyLatticeParSet


[docs] class DiffpyStructureParSet(SrRealParSet): """A wrapper for diffpy.structure.Structure. This class derives from diffpy.srfit.fitbase.parameterset.ParameterSet. See this class for base attributes. Attributes ---------- atoms The list of DiffpyAtomParSets, provided for convenience. stru The diffpy.structure.Structure this is adapting Managed ParameterSets --------------------- lattice The managed DiffpyLatticeParSet <el><idx> A managed DiffpyAtomParSets. <el> is the atomic element and <idx> is the index of that element in the structure, starting from zero. Thus, for nickel in P1 symmetry, the managed DiffpyAtomParSets will be named "Ni0", "Ni1", "Ni2" and "Ni3". """ def __init__(self, name, stru): """Initialize. Attributes ---------- name A name for the structure stru A diffpy.structure.Structure instance """ SrRealParSet.__init__(self, name) self.stru = stru self.addParameterSet(DiffpyLatticeParSet(stru.lattice)) self.atoms = [] cdict = {} for a in stru: el = a.element.title() # Try to sanitize the name. el = el.replace("+", "p") el = el.replace("-", "m") i = cdict.get(el, 0) aname = "%s%i" % (el, i) cdict[el] = i + 1 atom = DiffpyAtomParSet(aname, a) self.addParameterSet(atom) self.atoms.append(atom) return def __repr__(self): return repr(self.stru)
[docs] def getLattice(self): """Get the ParameterSet containing the lattice Parameters.""" return self.lattice
[docs] @classmethod def canAdapt(self, stru): """Return whether the structure can be adapted by this class.""" from diffpy.structure import Structure return isinstance(stru, Structure)
[docs] def getScatterers(self): """Get a list of ParameterSets that represents the scatterers. The site positions must be accessible from the list entries via the names "x", "y", and "z". The ADPs must be accessible as well, but the name and nature of the ADPs (U-factors, B-factors, isotropic, anisotropic) depends on the adapted structure. """ return self.atoms
def _getSrRealStructure(self): """Get the structure object for use with SrReal calculators. If this is periodic, then return the structure, otherwise, pass it inside of a nosymmetry wrapper. This takes the extra step of wrapping the structure in a nometa wrapper. """ from diffpy.srreal.structureadapter import nometa stru = SrRealParSet._getSrRealStructure(self) return nometa(stru)
# End class DiffpyStructureParSet