Skip to content

Instantly share code, notes, and snippets.

@dominikmuller
Created February 17, 2020 12:49
Show Gist options
  • Save dominikmuller/6dca46d78cf41f2d972e2cba896b8e10 to your computer and use it in GitHub Desktop.
Save dominikmuller/6dca46d78cf41f2d972e2cba896b8e10 to your computer and use it in GitHub Desktop.
from numpy import matrix
from numpy import zeros
from numpy import ones
from numpy import sqrt
import numpy
import logging as log
class DimensionError(numpy.linalg.LinAlgError):
pass
class BLUE:
"""A simple implementation of the Best Linear Unbiased Estimator, based on
"How to combine correlated estimates of a single physical quantity"
in NIM A, 270, pp 110-117"""
def __init__(self):
# List to store uncertainty sources and there cov matrices
self._vlist = []
def add_measurement(self, m_list):
"""Method to add the measured values. m_list has to give proper
len() and must be convertible to numpy.matrix objects. The length
of m_list defines the dimensionality of the average. Everything
else has to match this!"""
self._n_meas = len(m_list)
self._values = matrix(m_list)
# Now that we know the dimensions, initialise utility and storage
self._unit = matrix(ones(len(m_list))).T
self._ematrix = matrix(zeros((len(m_list), len(m_list))))
def add_source(self, v_matrix, name=''):
"""Add a source of uncertainty represented by the covariance
matrix of the measurements for this source. If name is specified,
the contributions of the uncertainty on the overall uncertainty
can be accessed."""
# matrix.n_dim returns a tuple of the dimensions, check that each
# is identical to the number of measurements
uncmatrix = matrix(v_matrix)
if False in [self._n_meas == x for x in uncmatrix.shape]:
raise DimensionError(
'Wrong shape. Expected {0}x{0}, got {1}x{2}'.format(
self._n_meas, *uncmatrix.shape))
if name:
self._vlist.append((name, uncmatrix))
self._ematrix += uncmatrix
def do(self):
log.debug('Total covariance matrix: \n {}'.format(self._ematrix))
self.weights = self._ematrix.I * self._unit
self.weights /= self._unit.T * self._ematrix.I * self._unit
log.debug('Weights: {}'.format(self.weights.T))
self.mean = (self._values*self.weights).max()
log.debug('Mean: {}'.format(self.mean))
self.error = sqrt(self.weights.T*self._ematrix*self.weights).max()
log.debug('Total uncertainty: {}'.format(self.error))
log.debug('Splitting errors based on input:')
for name, mat in self._vlist:
tmp_error = sqrt((self.weights.T*mat*self.weights).max())
setattr(self, name, tmp_error)
log.debug('{} : {}'.format(name, tmp_error))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment