Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/support masked array #263

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion filterpy/hinfinity/hinfinity_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def update(self, z):
measurement for this update.
"""

if z is None:
if z is None or z is np.ma.masked:
return

# rename for readability and a tiny extra bit of speed
Expand Down
2 changes: 1 addition & 1 deletion filterpy/kalman/CubatureKalmanFilter.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ def update(self, z, R=None, hx_args=()):
variable.
"""

if z is None:
if z is None or z is np.ma.masked:
self.z = np.array([[None]*self.dim_z]).T
self.x_post = self.x.copy()
self.P_post = self.P.copy()
Expand Down
2 changes: 1 addition & 1 deletion filterpy/kalman/EKF.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ def update(self, z, HJacobian, Hx, R=None, args=(), hx_args=(),
example, if they are angles)
"""

if z is None:
if z is None or z is np.ma.masked:
self.z = np.array([[None]*self.dim_z]).T
self.x_post = self.x.copy()
self.P_post = self.P.copy()
Expand Down
2 changes: 1 addition & 1 deletion filterpy/kalman/UKF.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ def update(self, z, R=None, UT=None, hx=None, **hx_args):
arguments to be passed into h(x) after x -> h(x, **hx_args)
"""

if z is None:
if z is None or z is np.ma.masked:
self.z = np.array([[None]*self._dim_z]).T
self.x_post = self.x.copy()
self.P_post = self.P.copy()
Expand Down
2 changes: 1 addition & 1 deletion filterpy/kalman/ensemble_kalman_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ def update(self, z, R=None):
one call, otherwise self.R will be used.
"""

if z is None:
if z is None or z is np.ma.masked:
self.z = array([[None]*self.dim_z]).T
self.x_post = self.x.copy()
self.P_post = self.P.copy()
Expand Down
2 changes: 1 addition & 1 deletion filterpy/kalman/fading_memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ def update(self, z, R=None):
one call, otherwise self.R will be used.
"""

if z is None:
if z is None or z is np.ma.masked:
self.z = np.array([[None]*self.dim_z]).T
self.x_post = self.x.copy()
self.P_post = self.P.copy()
Expand Down
2 changes: 1 addition & 1 deletion filterpy/kalman/information_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ def update(self, z, R_inv=None):
one call, otherwise self.R will be used.
"""

if z is None:
if z is None or z is np.ma.masked:
self.z = None
self.x_post = self.x.copy()
self.P_inv_post = self.P_inv.copy()
Expand Down
17 changes: 8 additions & 9 deletions filterpy/kalman/kalman_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ class KalmanFilter(object):

f.H = np.array([[1., 0.]])

Define the state's covariance matrix P.
Define the state's covariance matrix P.

.. code::

Expand Down Expand Up @@ -512,7 +512,7 @@ def update(self, z, R=None, H=None):
self._likelihood = None
self._mahalanobis = None

if z is None:
if z is None or z is np.ma.masked:
self.z = np.array([[None]*self.dim_z]).T
self.x_post = self.x.copy()
self.P_post = self.P.copy()
Expand Down Expand Up @@ -641,7 +641,7 @@ def update_steadystate(self, z):
self._likelihood = None
self._mahalanobis = None

if z is None:
if z is None or z is np.ma.masked:
self.z = np.array([[None]*self.dim_z]).T
self.x_post = self.x.copy()
self.P_post = self.P.copy()
Expand Down Expand Up @@ -702,7 +702,7 @@ def update_correlated(self, z, R=None, H=None):
self._likelihood = None
self._mahalanobis = None

if z is None:
if z is None or z is np.ma.masked:
self.z = np.array([[None]*self.dim_z]).T
self.x_post = self.x.copy()
self.P_post = self.P.copy()
Expand Down Expand Up @@ -1070,7 +1070,7 @@ def get_update(self, z=None):
State vector and covariance array of the update.
"""

if z is None:
if z is None or z is np.ma.masked:
return self.x, self.P
z = reshape_z(z, self.dim_z, self.x.ndim)

Expand Down Expand Up @@ -1183,7 +1183,7 @@ def log_likelihood_of(self, z):
after a call to update(). Calling after predict() will yield an
incorrect result."""

if z is None:
if z is None or z is np.ma.masked:
return log(sys.float_info.min)
return logpdf(z, dot(self.H, self.x), self.S)

Expand Down Expand Up @@ -1387,7 +1387,7 @@ def update(x, P, z, R, H=None, return_all=False):

#pylint: disable=bare-except

if z is None:
if z is None or z is np.ma.masked:
if return_all:
return x, P, None, None, None, None
return x, P
Expand Down Expand Up @@ -1476,8 +1476,7 @@ def update_steadystate(x, z, K, H=None):
>>> update_steadystate(x, P, z, H)
"""


if z is None:
if z is None or z is np.ma.masked:
return x

if H is None:
Expand Down
2 changes: 1 addition & 1 deletion filterpy/kalman/square_root.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ def update(self, z, R2=None):
be used.
"""

if z is None:
if z is None or z is np.ma.masked:
self.z = np.array([[None]*self.dim_z]).T
self.x_post = self.x.copy()
self._P1_2_post = np.copy(self._P1_2)
Expand Down
5 changes: 5 additions & 0 deletions filterpy/kalman/tests/test_kf.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,10 +268,15 @@ def test_batch_filter():
f.R = 5 # state uncertainty
f.Q = 0.0001 # process uncertainty

# Test with None for missing measurments
zs = [None, 1., 2.]
m, c, _, _ = f.batch_filter(zs, update_first=False)
m, c, _, _ = f.batch_filter(zs, update_first=True)

# Test with masked array for missing measurments
zs = np.ma.masked_invalid([np.nan, 1., 2.])
m, c, _, _ = f.batch_filter(zs, update_first=False)
m, c, _, _ = f.batch_filter(zs, update_first=True)

def test_univariate():
f = KalmanFilter(dim_x=1, dim_z=1, dim_u=1)
Expand Down
12 changes: 11 additions & 1 deletion filterpy/kalman/tests/test_ukf.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,11 @@ def hx(x):


def test_batch_missing_data():
""" batch filter should accept missing data with None in the measurements """
"""
Batch filter should accept missing data with None in the measurements

Alternatively, a masked array can be used.
"""

def fx(x, dt):
F = np.array([[1, dt, 0, 0],
Expand All @@ -456,11 +460,17 @@ def hx(x):
z = np.array([i + randn()*0.1, i + randn()*0.1])
zs.append(z)

# Test with None for missing measurments
zs[2] = None
Rs = [1]*len(zs)
Rs[2] = None
Ms, Ps = kf.batch_filter(zs)

# Test with masked array for missing measurments
zs[2] = np.nan
zs = np.ma.masked_invalid([np.nan, 1., 2.])
Ms, Ps = kf.batch_filter(zs)


def test_rts():
def fx(x, dt):
Expand Down
Loading