Source code for diffpy.srreal.sfaverage

#!/usr/bin/env python
##############################################################################
#
# diffpy.srreal     Complex Modeling Initiative
#                   (c) 2016 Brookhaven Science Associates,
#                   Brookhaven National Laboratory.
#                   All rights reserved.
#
# File coded by:    Pavol Juhas
#
# See AUTHORS.txt for a list of people who contributed.
# See LICENSE.txt for license information.
#
##############################################################################
"""Compositional averaging of atom scattering factors.

Examples
--------
::

    import numpy as np
    from diffpy.srreal.scatteringfactortable import SFTXray
    xtb = SFTXray()
    qa = np.linspace(0, 25)
    sfavg1 = SFAverage.fromComposition({'Na' : 1, 'Cl' : 1}, xtb, qa)
    sfavg2 = SFAverage.fromComposition([('Mn', 1), ('O', 2)], xtb, qa)

    from diffpy.structure import loadStructure
    from diffpy.srreal.pdfcalculator import DebyePDFCalculator
    dpdfc = DebyePDFCalculator()
    dpdfc(loadStructure('rutile.cif'))
    sfavg3 = SFAverage.fromStructure(dpdfc.getStructure(),
                                     dpdfc.scatteringfactortable, dpdfc.qgrid)
"""


# class SFAverage ------------------------------------------------------------


[docs] class SFAverage(object): """Calculate compositional statistics of atom scattering factors. Compositional averages can be calculated for an array of Q-values. Results are stored in the class attributes. Attributes ---------- f1sum : Sum of scattering factors from all atoms. Float or NumPy array. f2sum : Sum of squared scattering factors from all atoms. Float or NumPy array. count : Total number of atoms. Can be non-integer in case of fractional occupancies. f1avg : Compositional average of scattering factors. Float or NumPy array. f2avg : Compositional average of squared scattering factors. Float or NumPy array. composition : Dictionary of atom symbols and their total abundance. """ f1sum = 0 f2sum = 0 count = 0 f1avg = 0 f2avg = 0 composition = None
[docs] @classmethod def fromStructure(cls, stru, sftb, q=0): """Calculate average scattering factors from a structure object. Parameters ---------- stru : diffpy Structure or pyobjcryst Crystal or StructureAdapter The structure object that stores the atom species and their occupancies. Can be any type with a registered conversion to the StructureAdapter class. sftb : ScatteringFactorTable or str The ScatteringFactorTable object for looking up the values. When string use `ScatteringFactorTable.createByType` to create a new lookup table of the specified type. q : float or NumPy array (optional) The Q value in inverse Angstroms for which to lookup the scattering factor values. See also -------- RegisterStructureAdapter : to add support for more structure types. Returns ------- SFAverage The calculated scattering factor averages. """ # a bit of duck-typing for faster handling of diffpy.structure if hasattr(type(stru), "composition"): composition = stru.composition if isinstance(composition, dict): return cls.fromComposition(composition, sftb, q) # otherwise let's convert to a known structure type from diffpy.srreal.structureadapter import createStructureAdapter adpt = createStructureAdapter(stru) composition = {} for i in range(adpt.countSites()): smbl = adpt.siteAtomType(i) cnt = adpt.siteOccupancy(i) * adpt.siteMultiplicity(i) composition[smbl] = composition.get(smbl, 0) + cnt return cls.fromComposition(composition, sftb, q)
[docs] @classmethod def fromComposition(cls, composition, sftb, q=0): """Calculate average scattering factors from atom concentrations. Parameters ---------- composition : dictionary or a list of (symbol, amount) pairs. The chemical composition for evaluating the average. Atom symbols may repeat when it is a list of (symbol, amount) pairs. sftb : ScatteringFactorTable or str The ScatteringFactorTable object for looking up the values. When string use `ScatteringFactorTable.createByType` to create a new lookup table of the specified type. q : float or NumPy array (optional) The Q value in inverse Angstroms for which to lookup the scattering factor values. Returns ------- SFAverage The calculated scattering factor averages. """ from diffpy.srreal.scatteringfactortable import ScatteringFactorTable sfa = cls() sfa.composition = {} if isinstance(composition, dict): sfa.composition.update(composition) else: for smbl, cnt in composition: if smbl not in sfa.composition: sfa.composition[smbl] = 0 sfa.composition[smbl] += cnt sfa.f1sum = 0.0 * q sfa.f2sum = 0.0 * q # resolve the lookup table object `tb` tb = ( sftb if not isinstance(sftb, str) else ScatteringFactorTable.createByType(sftb) ) for smbl, cnt in sfa.composition.items(): sfq = tb.lookup(smbl, q) sfa.f1sum += cnt * sfq sfa.f2sum += cnt * sfq**2 sfa.count += cnt denom = sfa.count if sfa.count > 0 else 1 sfa.f1avg = sfa.f1sum / denom sfa.f2avg = sfa.f2sum / denom return sfa
# End of class SFAverage