Source code for orbit.utils.fitting.PolynomialFit
# -------------------------------------------------------------------------
# This is a polynom fitting class. It uses the standart
# LSM nmatrix approach.
# As input you can use Function or SplineCH instances
# order of the polynomial a0+...+aN*x^N is N
# --------------------------------------------------------------------------
import sys
import math
from orbit.core.orbit_utils import Function, SplineCH
from orbit.core.orbit_utils import PhaseVector, Matrix
from orbit.core.orbit_utils import Polynomial
[docs]class PolynomialFit:
[docs] def __init__(self, order):
"""The calss to fit Function or SplineCH with a polynomial."""
self.order = order
self.polynomial = Polynomial()
# self.coef_err_arr is a final array with coef_arr and err_arr for polinomial coefficients
self.coef_err_arr = []
# self.x_y_err_arr is initial data with (x,y,y_err) points
self.x_y_err_arr = []
def getPolynomial(self):
"""It returns an unbounded polynomial."""
polynomial = Polynomial()
self.polynomial.copyTo(polynomial)
return polynomial
def getCoefficientsAndErr(self):
"""It returns the list of coefficients and their errors"""
return self.coef_err_arr
def getCoefficients(self):
"""Returns the list of coefficients of the polynomial"""
coef_arr = []
for i in range(len(self.coef_err_arr)):
[coef, err] = self.coef_err_arr[i]
coef_arr.append(coef)
return coef_arr
def fitFunction(self, function):
"""Fit the Function instance"""
self.x_y_err_arr = []
for i in range(function.getSize()):
x = function.x(i)
y = function.y(i)
err = function.err(i)
self.x_y_err_arr.append([x, y, err])
self._makePolynomial()
def fitSpline(self, spline):
"""Fit the SplineCH instance"""
self.x_y_err_arr = []
for i in range(spline.getSize()):
x = spline.x(i)
y = spline.y(i)
err = 0.0
self.x_y_err_arr.append([x, y, err])
self._makePolynomial()
def _makePolynomial(self):
nPoints = len(self.x_y_err_arr)
if(nPoints < (self.order + 1)):
self.order = nPoints - 1
#---- now make A and A^T matrices and y-vector
aMtr = Matrix(nPoints, self.order + 1)
yVct = PhaseVector(nPoints)
for i in range(nPoints):
y = self.x_y_err_arr[i][1]
yVct.set(i,y)
for j in range(self.order + 1):
x = self.x_y_err_arr[i][0]
aMtr.set(i, j, math.pow(x, j))
aMtrT = aMtr.transpose()
# now the resuting coefficients and errors
ATA_inv = (aMtrT.mult(aMtr)).invert()
coeffVct = (ATA_inv.mult(aMtrT)).mult(yVct)
# polinimial coefficients have been found -> coeffVct
coef_arr = [0.0] * (self.order + 1)
self.polynomial.order(self.order)
for i in range(self.order + 1):
coef_arr[i] = coeffVct.get(i)
self.polynomial.coefficient(i,coef_arr[i])
#---- here we estimate errors by deviation y_fit from y_init only
#---- It means that we do not pay attention to different weights
#---- of the initial Y data errors
coeff_err_arr = [0.0] * (self.order + 1)
for i in range(self.order + 1):
coeff_err_arr[i] = math.sqrt(ATA_inv.get(i,i))
total_sigma = 0.0
for k in range(nPoints):
x = self.x_y_err_arr[k][0]
y = self.x_y_err_arr[k][1]
total_sigma += (self.polynomial.value(x) - y) ** 2
degrees_of_freedom = int(abs(nPoints - (self.order + 1)))
if(degrees_of_freedom == 0): degrees_of_freedom = 1
total_sigma = math.sqrt(total_sigma / degrees_of_freedom)
for i in range(self.order + 1):
coeff_err_arr[i] *= total_sigma
# set the resulting coefficients and errors array
self.coef_err_arr = [coef_arr, coeff_err_arr]