Source code for error_solver.solvers._base_error_solver
import numpy as np
import pandas as pd
__all__ = ['_BaseErrorSolver']
class _BaseErrorSolver(object):
def get_equations(self, combo=None):
"""
Returns a list of equations for the specified combination.
If `combo` is None, a list of all equations will be returned.
Parameters
----------
combo : str
The name of the equation combination to be applied.
"""
if combo is None:
return self._equations
else:
return [self._equations[i] for i in self.combos[combo]]
def get_partials(self, combo=None):
"""
Returns a list of partial derivatives for the specified combination.
If `combo` is None, a list of all partial derivatives will be returned.
Parameters
----------
combo : str
The name of the equation combination to be applied.
"""
if combo is None:
return self._partials
else:
return [self._partials[i] for i in self.combos[combo]]
def used_vars(self, values, errors, combo=None):
"""
Returns a lists of (1) variables present in both the equations and
input values dictionary and (2) variables present in both the equations
and input errors dictionary.
Parameters
----------
values : dict
A dictionary mapping variable names to values.
errors : dict
A dictionary mapping variable names to errors.
combo : str
The name of the equation combination to be applied.
"""
var = self.equation_vars(combo)
err = var.intersection(errors)
val = var.intersection(values) - err
return sorted(val), sorted(err)
def _check_determinancy(self, values, errors, combo):
"""
Checks that the system of equations is determinant, i.e. that the
number of unknown errors equals the number of equations.
Parameters
----------
values : dict
A dictionary mapping variable names to values.
errors : dict
A dictionary mapping variable names to errors.
combo : str
The name of the equation combination to be applied.
"""
val, err = self.used_vars(values, errors, combo)
n, m = len(val), len(self.get_equations(combo))
if n != m:
if m > n:
s = '>'
t = 'remove'
v = err
else:
s = '<'
t = 'add'
v = val
a = abs(n - m)
raise ValueError('Indeterminant system:: Number of equations ({}) '
'{} number of unknowns ({}). To correct, {} ({}) errors in {} '
'or adjust the input equations.'.format(m, s, n, t, a, v))
def solve(self, values, errors, const={}, combo=None, check=True, stdev=False):
"""
Solves for the propagation errors of the system of equations and
returns a Data Frame of the results.
Parameters
----------
values : dict
A dictionary mapping variable names to values.
errors : dict
A dictionary mapping variable names to errors.
const : dict
A dictionary mapping variable names to constant errors.
combo : str
The name of the equation combination to be applied.
check : bool
If True, value and other analysis checks will be performed
prior to calculating the solution.
stdev : bool
If True, error values input are for standard deviations. Otherwise,
the values represent error tolerances or variances.
"""
if check:
self.check(values, errors, combo)
val, err = self.used_vars(values, errors, combo)
n, m = len(val), len(err)
xk = np.array([errors[k] for k in err], dtype='float').reshape(-1, 1)
jac = self.jacobian(values, errors, combo)
ju, jk = jac[:,:n], jac[:,n:n+m]
jui = np.abs(np.linalg.inv(ju))
ju, jk = np.abs(ju), np.abs(jk)
if const:
ck = np.array([const.get(k, 0) for k in err], dtype='float').reshape(-1, 1)
cu = np.array([const.get(k, 0) for k in val], dtype='float').reshape(-1, 1)
if stdev:
xk **= 2
ck **= 2
cu **= 2
xk += ck
else:
xk = np.abs(xk)
ck = np.abs(ck)
cu = np.abs(cu)
xk += ck
xu = jui.dot(jk.dot(xk) + ju.dot(cu))
del jac, jui, ju, jk, cu, ck
else:
if stdev:
xk **= 2
else:
xk = np.abs(xk)
xu = jui.dot(jk.dot(xk))
del jac, jui, ju, jk
if stdev:
xu **= 0.5
xk **= 0.5
xu = xu.ravel()
xk = xk.ravel()
# Create data frame of results
df = pd.DataFrame()
df['var'] = val + err
df['value'] = [values[k] for k in df['var']]
df['error'] = np.concatenate([xu, xk])
df['pct_error'] = 100 * abs(df['error'] / df['value'])
df['is_calc'] = np.concatenate([np.ones(n), np.zeros(m)]).astype('bool')
df.sort_values('var', inplace=True)
df.replace(float('inf'), np.nan, inplace=True)
df.set_index('var', inplace=True)
return df