Source code for diffpy.srfit.fitbase.restraint

#!/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.
#
##############################################################################
"""Restraints class.

Restraints are used by RecipeOrganizers to organize restraint equations.
Restraints store an Equation, bounds on its value, and the form of the
penalty function for breaking a restraint. This penalty is added to the
residual equation calculated by a FitRecipe.
"""

__all__ = ["Restraint"]

from numpy import inf

from diffpy.srfit.exceptions import SrFitError
from diffpy.srfit.fitbase.validatable import Validatable


[docs] class Restraint(Validatable): """Restrain an equation to specified bounds. The penalty for breaking the restraint is calculated as ``(max(0, lower_bound - val, val - upper_bound) / sig) ** 2``, where ``val`` is the value of the calculated equation. This is multiplied by the average chi^2 if ``scaled`` is True. Attributes ---------- eq : Equation The equation whose evaluation is compared against the restraint bounds. lower_bound : float The lower bound on the restraint evaluation (default -inf). upper_bound : float The upper bound on the restraint evaluation (default inf). sig : float The uncertainty on the bounds (default 1). scaled : bool A flag indicating if the restraint is scaled (multiplied) by the unrestrained point-average chi^2 (chi^2/numpoints) (default False). """ def __init__( self, eq, lower_bound=-inf, upper_bound=inf, sig=1, scaled=False ): """Restrain an equation to specified bounds. Parameters ---------- eq : Equation The equation whose evaluation is compared against the restraint bounds. lower_bound : float, optional The lower bound on the restraint evaluation (default -inf). upper_bound : float, optional The upper bound on the restraint evaluation (default inf). sig : float, optional The uncertainty on the bounds (default 1). scaled : bool, optional The flag indicating if the restraint is scaled (multiplied) by the unrestrained point-average chi^2 (chi^2/numpoints) (default False). """ self.eq = eq self.lower_bound = float(lower_bound) self.upper_bound = float(upper_bound) self.sig = float(sig) self.scaled = bool(scaled) return
[docs] def penalty(self, w=1.0): """Calculate the penalty of the restraint. Parameters ---------- w : float, optional The point-average chi^2 which is optionally used to scale the penalty (default 1.0). Returns ------- float The penalty for breaking the restraint. """ val = self.eq() penalty = ( max(0, self.lower_bound - val, val - self.upper_bound) / self.sig ) ** 2 if self.scaled: penalty *= w return penalty
def _validate(self): """Validate my state. This validates ``eq``. Raises ------ SrFitError If validation fails. """ if self.eq is None: raise SrFitError("eq is None") from diffpy.srfit.equation.visitors import validate try: validate(self.eq) except ValueError as e: raise SrFitError(e) # Try to get the value of eq. try: val = self.eq() except TypeError: raise SrFitError("eq cannot be evaluated") finally: if val is None: raise SrFitError("eq evaluates to None") return
# End class Restraint # End of file