#!/usr/bin/env python
##############################################################################
#
# diffpy.srfit by DANSE Diffraction group
# Simon J. L. Billinge
# (c) 2008 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.
#
##############################################################################
"""The ProfileGenerator class for generating a profile.
ProfileGenerators encapsulate the evaluation and required Parameters and
ParameterSets of a profile calculator. The ProfileGenerator class can
be associated with a FitContribution to help calculate a profile.
To define a ProfileGenerator, one must implement the required Parameters
and ParameterSets as well as overload the __call__ method with the
calculation. A very simple example is
.. code:: python
class Gaussian(ProfileGenerator):
def __init__(self):
# Initialize and give this a name
ProfileGenerator.__init__(self, "g")
# Add amplitude, center and width parameters
self.newParameter("amp", 0)
self.newParameter("center", 0)
self.newParameter("width", 0)
def __call__(self, x):
a = self.amp.getValue()
x0 = self.center.getValue()
w = self.width.getValue()
return a * exp(-0.5*((x-x0)/w)**2)
More examples can be found in the example directory of the
documentation.
"""
__all__ = ["ProfileGenerator"]
from diffpy.srfit.equation.literals.operators import Operator
from diffpy.srfit.exceptions import SrFitError
from diffpy.srfit.fitbase.parameterset import ParameterSet
[docs]
class ProfileGenerator(Operator, ParameterSet):
"""Base class for profile generators.
A ProfileGenerator organizes Parameters and has a __call__ method that can
generate a profile. ProfileGenerator is also an Operator
(diffpy.srfit.equation.literals.operators), so it can be used directly in
an evaluation network.
Attributes
----------
name
A name for this organizer.
profile
A Profile instance that contains the calculation range
and will contain the generated profile.
meta
A dictionary of metadata needed by the generator.
eq
The Equation object used to wrap this ProfileGenerator.
This is set when the ProfileGenerator is added to a
FitContribution.
_calculators
A managed dictionary of Calculators, indexed by name.
_constraints
A set of constrained Parameters. Constraints can be
added using the 'constrain' methods.
_parameters
A managed OrderedDict of contained Parameters.
_parsets
A managed dictionary of ParameterSets.
_restraints
A set of Restraints. Restraints can be added using the
'restrain' or 'confine' methods.
_eqfactory
A diffpy.srfit.equation.builder.EquationFactory
instance that is used create Equations from string.
Operator Attributes
-------------------
args
List of Literal arguments, set with 'addLiteral'
name
A name for this operator. e.g. "add" or "sin"
nin
Number of inputs (<1 means this is variable)
nout
Number of outputs
operation
Function that performs the operation. e.g. numpy.add. In
this case, operation is an instance method.
symbol
The symbolic representation. e.g. "+" or "sin"
_value
The value of the Operator.
value
Property for 'getValue'.
Properties
----------
names
Variable names (read only). See getNames.
values
Variable values (read only). See getValues.
"""
# define abstract attributes from the Operator base.
nin = 0
nout = 1
def __init__(self, name):
"""Initialize the attributes."""
Operator.__init__(self)
ParameterSet.__init__(self, name)
self.profile = None
self.meta = {}
return
@property
def symbol(self):
return self.name
# Overload me!
def __call__(self, x):
"""Evaluate the profile.
This method must be overloaded.
This method only takes the independent variables to calculate
over.
"""
return x
# No need to overload anything below here
[docs]
def operation(self):
"""Evaluate the profile.
Return the result of __call__(profile.x).
"""
y = self.__call__(self.profile.x)
return y
[docs]
def setProfile(self, profile):
"""Assign the profile.
Attributes
----------
profile
A Profile that specifies the calculation points and which
will store the calculated signal.
"""
if self.profile is not None:
self.profile.removeObserver(self._flush)
self.profile = profile
self.profile.addObserver(self._flush)
self._flush(other=(self,))
# Merge the profiles metadata with our own
self.meta.update(self.profile.meta)
self.processMetaData()
return
def _validate(self):
"""Validate my state.
This performs profile validations. This performs ParameterSet
validations. This does not validate the operation, since this
could be costly. The operation should be validated with a
containing equation.
Raises SrFitError if validation fails.
"""
if self.profile is None:
raise SrFitError("profile is None")
self.profile._validate()
ParameterSet._validate(self)
return
# End class ProfileGenerator