Source code for scisalt.scipy.LinLsqFit
import os as _os
on_rtd = _os.environ.get('READTHEDOCS', None) == 'True'
if not on_rtd:
import numpy as _np
from .chisquare import chisquare
import copy as _copy
[docs]class LinLsqFit(object):
"""
Gets the linear least squares for :math:`\\beta` of a problem given :math:`X_{ij} \\beta_{i} = y_j`.
As input, it takes *y_unweighted* as the measured :math:`y`, *X_unweighted* for :math:`X`, and *y_error* as the measurement error on :math:`y`.
"""
_resetlist = ['_X', '_y', '_beta', '_covar', '_chisq_red', '_y_fit']
def __init__(self, y_unweighted, X_unweighted, y_error=None):
self._force_recalc()
self.y_unweighted = y_unweighted
self.y_error = y_error
self.X_unweighted = X_unweighted
# ======================================
# Resets stored values for calculated
# quantities
# ======================================
def _force_recalc(self):
# self._X = None
# self._y = None
# self._beta = None
# self._covar = None
# self._chisq_red = None
# self._emit = None
# self._twiss=None
for resetstr in self._resetlist:
# print resetstr
setattr(self, resetstr, None)
# ======================================
# y_unweighted
# ======================================
@property
def y_unweighted(self):
"""
The :math:`y` of the problem :math:`X_{ij} \\beta_{i} = y_j`. Setting this attribute forces a recalculation.
"""
return self._y_unweighted
@y_unweighted.setter
def y_unweighted(self, val):
self._force_recalc()
self._y_unweighted = val
# ======================================
# y_error
# ======================================
@property
def y_error(self):
"""
The measured error of :math:`y` of the problem :math:`X_{ij} \\beta_{i} = y_j`. Setting this attribute forces a recalculation.
"""
return self._y_error
@y_error.setter
def _set_y_error(self, val):
self._force_recalc()
self._y_error = val
# ======================================
# X_unweighted
# ======================================
@property
def X_unweighted(self):
"""
The :math:`X`. Setting this attribute forces a recalculation.
"""
return self._X_unweighted
@X_unweighted.setter
def _set_X_unweighted(self, val):
self._force_recalc()
self._X_unweighted = val
# ======================================
# X (calculated)
# ======================================
@property
def X(self):
"""
The :math:`X` weighted properly by the errors from *y_error*
"""
if self._X is None:
X = _copy.deepcopy(self.X_unweighted)
# print 'X shape is {}'.format(X.shape)
for i, el in enumerate(X):
X[i, :] = el/self.y_error[i]
# print 'New X shape is {}'.format(X.shape)
self._X = X
return self._X
# ======================================
# y (calculated)
# ======================================
@property
def y(self):
"""
The :math:`X` weighted properly by the errors from *y_error*
"""
if self._y is None:
self._y = self.y_unweighted/self.y_error
return self._y
# ======================================
# y_fit (y from fit)
# ======================================
@property
def y_fit(self):
"""
Using the result of the linear least squares, the result of :math:`X_{ij}\\beta_i`
"""
if self._y_fit is None:
self._y_fit = _np.dot(self.X_unweighted, self.beta)
return self._y_fit
# ======================================
# beta (calculated)
# ======================================
@property
def beta(self):
"""
The result :math:`\\beta` of the linear least squares
"""
if self._beta is None:
# This is the linear least squares matrix formalism
self._beta = _np.dot(_np.linalg.pinv(self.X) , self.y)
return self._beta
# ======================================
# covar (calculated)
# ======================================
@property
def covar(self):
"""
The covariance matrix for the result :math:`\\beta`
"""
if self._covar is None:
self._covar = _np.linalg.inv(_np.dot(_np.transpose(self.X), self.X))
return self._covar
# ======================================
# chisq_red (calculated)
# ======================================
@property
def chisq_red(self):
"""
The reduced chi-square of the linear least squares
"""
if self._chisq_red is None:
self._chisq_red = chisquare(self.y_unweighted.transpose(), _np.dot(self.X_unweighted, self.beta), self.y_error, ddof=3, verbose=False)
return self._chisq_red