#!/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.
#
##############################################################################
"""Simple FitRecipe class that includes a FitContribution and
Profile."""
from diffpy.srfit.fitbase.fitcontribution import FitContribution
from diffpy.srfit.fitbase.fitrecipe import FitRecipe
from diffpy.srfit.fitbase.fitresults import FitResults
from diffpy.srfit.fitbase.profile import Profile
from diffpy.utils._deprecator import build_deprecation_message, deprecated
base = "diffpy.srfit.fitbase.SimpleRecipe"
removal_version = "4.0.0"
loadParsedData_dep_msg = build_deprecation_message(
base,
"loadParsedData",
"load_parsed_data",
removal_version,
)
setObservedProfile_dep_msg = build_deprecation_message(
base,
"setObservedProfile",
"set_observed_profile",
removal_version,
)
setCalculationRange_dep_msg = build_deprecation_message(
base,
"setCalculationRange",
"set_calculation_range",
removal_version,
)
setCalculationPoints_dep_msg = build_deprecation_message(
base,
"setCalculationPoints",
"set_calculation_points",
removal_version,
)
setEquation_dep_msg = build_deprecation_message(
base,
"setEquation",
"set_equation",
removal_version,
)
printResults_dep_msg = build_deprecation_message(
base,
"printResults",
"print_results",
removal_version,
)
saveResults_dep_msg = build_deprecation_message(
base,
"saveResults",
"save_results",
removal_version,
)
[docs]
class SimpleRecipe(FitRecipe):
"""FitRecipe with a built-in Profile and FitContribution.
This is a FitRecipe with a built-in Profile (the 'profile' attribute) and
FitContribution (the 'contribution' attribute). Unique methods from each of
these are exposed through this class to facilitate the creation of a simple
fit recipe.
Attributes
----------
profile
The built-in Profile object.
contribution
The built-in FitContribution object.
results
The built-in FitResults object.
name
A name for this FitRecipe.
fithooks : list
The list of FitHook instances that can pass information out
of the system during a refinement. By default, this is
populated by a PrintFitHook instance.
_constraints
A dictionary of Constraints, indexed by the constrained
Parameter. Constraints can be added using the
'constrain' method.
_oconstraints
An ordered list of the constraints from this and all
sub-components.
_calculators
A managed dictionary of Calculators.
_contributions
A managed OrderedDict of FitContributions.
_parameters
A managed OrderedDict of parameters (in this case the
parameters are varied).
_parsets
A managed dictionary of ParameterSets.
_eqfactory
A diffpy.srfit.equation.builder.EquationFactory
instance that is used to create constraints and
restraints from string equations.
_fixed
A set of parameters that are not actually varied.
_restraintlist
A list of restraints from this and all sub-components.
_restraints
A set of Restraints. Restraints can be added using the
'restrain' or 'confine' methods.
_ready
A flag indicating if all attributes are ready for the
calculation.
_tagdict
A dictionary of tags to variables.
_weights
List of weighing factors for each FitContribution. The
weights are multiplied by the residual of the
FitContribution when determining the overall residual.
Properties
----------
names
Variable names (read only). See get_names.
values
Variable values (read only). See get_values.
"""
def __init__(self, name="fit", conclass=FitContribution):
"""Initialize the recipe with a built-in Profile and
FitContribution.
Parameters
----------
name : str, optional
The name of this FitRecipe (default "fit").
conclass : type, optional
The FitContribution class used to create the built-in
contribution (default FitContribution).
"""
FitRecipe.__init__(self, name)
self.fithooks[0].verbose = 3
contribution = conclass("contribution")
self.profile = Profile()
contribution.set_profile(self.profile)
self.add_contribution(contribution)
self.results = FitResults(self, update=False)
# Adopt all the FitContribution methods
public = [
aname
for aname in dir(contribution)
if aname not in dir(self) and not aname.startswith("_")
]
for mname in public:
method = getattr(contribution, mname)
setattr(self, mname, method)
return
# Profile methods
[docs]
def load_parsed_data(self, parser):
"""Load parsed data from a ProfileParser.
This sets the xobs, yobs, dyobs arrays as well as the metadata.
Parameters
----------
parser : ProfileParser
The ProfileParser to load data from.
"""
return self.profile.load_parsed_data(parser)
[docs]
@deprecated(loadParsedData_dep_msg)
def loadParsedData(self, parser):
"""This function has been deprecated and will be removed in version
4.0.0.
Please use
diffpy.srfit.fitbase.SimpleRecipe.load_parsed_data
instead.
"""
return self.load_parsed_data(parser)
[docs]
def set_observed_profile(self, xobs, yobs, dyobs=None):
"""Set the observed profile.
Parameters
----------
xobs : ndarray
The independent variable.
yobs : ndarray
The observed signal.
dyobs : ndarray, optional
The uncertainty in the observed signal. If dyobs is None
(default), it will be set to 1 at each observed xobs.
Raises
------
ValueError
If len(yobs) != len(xobs), or if dyobs is not None and
len(dyobs) != len(xobs).
"""
return self.profile.set_observed_profile(xobs, yobs, dyobs)
[docs]
@deprecated(setObservedProfile_dep_msg)
def setObservedProfile(self, xobs, yobs, dyobs=None):
"""This function has been deprecated and will be removed in version
4.0.0.
Please use
diffpy.srfit.fitbase.SimpleRecipe.set_observed_profile
instead.
"""
return self.set_observed_profile(xobs, yobs, dyobs)
[docs]
def set_calculation_range(self, xmin=None, xmax=None, dx=None):
"""Set epsilon-inclusive calculation range.
Adhere to the observed ``xobs`` points when ``dx`` is the same
as in the data. ``xmin`` and ``xmax`` are clipped at the bounds
of the observed data.
Parameters
----------
xmin : float or `obs`, optional
The minimum value of the independent variable. Keep the
current minimum when not specified. If specified as "obs"
reset to the minimum observed value.
xmax : float or `obs`, optional
The maximum value of the independent variable. Keep the
current maximum when not specified. If specified as "obs"
reset to the maximum observed value.
dx : float or `obs`, optional
The sample spacing in the independent variable. When different
from the data, resample the ``x`` as anchored at ``xmin``.
Note that ``xmin`` is always inclusive (unless clipped).
``xmax`` is inclusive if it is within the bounds of the observed data.
Raises
------
AttributeError
If there is no observed data.
ValueError
When xmin > xmax or if dx <= 0. Also if dx > xmax - xmin.
"""
return self.profile.set_calculation_range(xmin, xmax, dx)
[docs]
@deprecated(setCalculationRange_dep_msg)
def setCalculationRange(self, xmin=None, xmax=None, dx=None):
"""This function has been deprecated and will be removed in version
4.0.0.
Please use
diffpy.srfit.fitbase.SimpleRecipe.set_calculation_range
instead.
"""
return self.set_calculation_range(xmin, xmax, dx)
[docs]
def set_calculation_points(self, x):
"""Set the calculation points.
This will create y and dy on the specified grid if xobs, yobs
and dyobs exist.
Parameters
----------
x : ndarray
The non-empty array of calculation points. If xobs exists,
the bounds of x will be limited to its bounds.
"""
return self.profile.set_calculation_points(x)
[docs]
@deprecated(setCalculationPoints_dep_msg)
def setCalculationPoints(self, x):
"""This function has been deprecated and will be removed in version
4.0.0.
Please use
diffpy.srfit.fitbase.SimpleRecipe.set_calculation_points
instead.
"""
return self.set_calculation_points(x)
[docs]
def loadtxt(self, *args, **kw):
"""Use numpy.loadtxt to load data.
Arguments are passed to numpy.loadtxt. unpack = True is
enforced. The first two arrays returned by numpy.loadtxt are
assumed to be x and y. If there is a third array, it is assumed
to by dy. Any other arrays are ignored. These are passed to
set_observed_profile.
Raises
------
ValueError
If the call to numpy.loadtxt returns fewer than 2 arrays.
Returns
-------
tuple
The x, y and dy arrays loaded from the file.
"""
return self.profile.loadtxt(*args, **kw)
# FitContribution
[docs]
def set_equation(self, eqstr, ns={}):
"""Set the profile equation for the FitContribution.
This sets the equation that will be used when generating the residual.
The equation will be usable within set_residual_equation as "eq", and
it takes no arguments.
Parameters
----------
eqstr : str
The string representation of the equation. Variables will
be extracted from this equation and be given an initial
value of 0.
ns : dict, optional
The dictionary of Parameters, indexed by name, that are
used in the eqstr, but not registered (default {}).
Raises
------
ValueError
If ns uses a name that is already used for a variable.
"""
self.contribution.set_equation(eqstr, ns={})
# Extract variables
for par in self.contribution:
# Skip Profile Parameters
if par.name in ("x", "y", "dy"):
continue
if par.value is None:
par.value = 0
if par.name not in self._parameters:
self.add_variable(par)
return
[docs]
@deprecated(setEquation_dep_msg)
def setEquation(self, eqstr, ns={}):
"""This function has been deprecated and will be removed in version
4.0.0.
Please use
diffpy.srfit.fitbase.SimpleRecipe.set_equation
instead.
"""
self.set_equation(eqstr, ns)
return
def __call__(self):
"""Evaluate the contribution equation."""
return self.contribution.evaluate()
# FitResults methods
[docs]
def print_results(self, header="", footer=""):
"""Format and print the results.
Parameters
----------
header : str, optional
The header to add to the output (default "").
footer : str, optional
The footer to add to the output (default "").
"""
self.results.print_results(header, footer, True)
return
[docs]
@deprecated(printResults_dep_msg)
def printResults(self, header="", footer=""):
"""This function has been deprecated and will be removed in version
4.0.0.
Please use
diffpy.srfit.fitbase.SimpleRecipe.print_results
instead.
"""
self.print_results(header, footer)
return
[docs]
def save_results(self, filename, header="", footer=""):
"""Format and save the results.
Parameters
----------
filename : str
The name of the save file.
header : str, optional
The header to add to the output (default "").
footer : str, optional
The footer to add to the output (default "").
"""
self.results.save_results(filename, header, footer, True)
[docs]
@deprecated(saveResults_dep_msg)
def saveResults(self, filename, header="", footer=""):
"""This function has been deprecated and will be removed in version
4.0.0.
Please use
diffpy.srfit.fitbase.SimpleRecipe.save_results
instead.
"""
self.save_results(filename, header, footer)
# End class SimpleRecipe
# End of file