diff --git a/src/progpy/state_estimators/unscented_kalman_filter.py b/src/progpy/state_estimators/unscented_kalman_filter.py index aaa7b36..810a2c3 100644 --- a/src/progpy/state_estimators/unscented_kalman_filter.py +++ b/src/progpy/state_estimators/unscented_kalman_filter.py @@ -2,7 +2,7 @@ from filterpy import kalman from numpy import diag, array -from warnings import warn +from warnings import warn, catch_warnings, simplefilter from progpy.state_estimators import state_estimator from progpy.uncertain_data import MultivariateNormalDist, UncertainData @@ -54,22 +54,28 @@ def __init__(self, model, x0, **kwargs): # Saving for reduce pickling def measure(x): + # Disable deprecation warnings for internal progpy code. x = model.StateContainer({key: value for (key, value) in zip(x0.keys(), x)}) R_err = model.parameters['measurement_noise'].copy() - model.parameters['measurement_noise'] = dict.fromkeys(R_err, 0) - z = model.output(x) - model.parameters['measurement_noise'] = R_err - return array(list(z.values())).ravel() + with catch_warnings(): + simplefilter("ignore", DeprecationWarning) + model.parameters['measurement_noise'] = dict.fromkeys(R_err, 0) + z = model.output(x) + model.parameters['measurement_noise'] = R_err + return array(list(z.values())).ravel() if 'Q' not in self.parameters: self.parameters['Q'] = diag([1.0e-3 for _ in x0.keys()]) def state_transition(x, dt): + # Disable deprecation warnings for internal progpy code. x = model.StateContainer({key: value for (key, value) in zip(x0.keys(), x)}) Q_err = model.parameters['process_noise'].copy() - model.parameters['process_noise'] = dict.fromkeys(Q_err, 0) - x = model.next_state(x, self.__input, dt) - return array(list(x.values())).ravel() + with catch_warnings(): + simplefilter("ignore", DeprecationWarning) + model.parameters['process_noise'] = dict.fromkeys(Q_err, 0) + x = model.next_state(x, self.__input, dt) + return array(list(x.values())).ravel() num_states = len(x0.keys()) num_measurements = model.n_outputs diff --git a/src/progpy/utils/containers.py b/src/progpy/utils/containers.py index 7323969..092858b 100644 --- a/src/progpy/utils/containers.py +++ b/src/progpy/utils/containers.py @@ -69,20 +69,21 @@ def frame(self) -> pd.DataFrame: Returns: frame - pd.DataFrame """ warn('frame will be deprecated after version 1.5 of ProgPy.', DeprecationWarning, stacklevel=2) - self._frame = pd.DataFrame(self.matrix.T, columns=self._keys) + self._frame = pd.DataFrame(self._matrix.T, columns=self._keys) return self._frame def __reduce__(self): """ reduce is overridden for pickles """ - return (DictLikeMatrixWrapper, (self._keys, self.matrix)) + return (DictLikeMatrixWrapper, (self._keys, self._matrix)) def __getitem__(self, key: str) -> int: """ get all values associated with a key, ex: all values of 'i' """ - row = self.matrix[self._keys.index(key)] # creates list from a row of matrix + # Disable deprecation warnings for internal progpy code. + row = self._matrix[self._keys.index(key)] # creates list from a row of matrix if len(row) == 1: # list contains 1 value, returns that value (non-vectorized) return row[0] return row # returns entire row/list (vectorized case) @@ -92,20 +93,20 @@ def __setitem__(self, key: str, value: int) -> None: sets a row at the key given """ index = self._keys.index(key) # the int value index for the key given - self.matrix[index] = np.atleast_1d(value) + self._matrix[index] = np.atleast_1d(value) def __delitem__(self, key: str) -> None: """ removes row associated with key """ - self.matrix = np.delete(self.matrix, self._keys.index(key), axis=0) + self._matrix = np.delete(self._matrix, self._keys.index(key), axis=0) self._keys.remove(key) def __add__(self, other: "DictLikeMatrixWrapper") -> "DictLikeMatrixWrapper": """ add another matrix to the existing matrix """ - return DictLikeMatrixWrapper(self._keys, self.matrix + other.matrix) + return DictLikeMatrixWrapper(self._keys, self._matrix + other.matrix) def __iter__(self): """ @@ -124,11 +125,11 @@ def equals(self, other): if isinstance(other, dict): # checks that the list of keys for each matrix match list_key_check = (list(self.keys()) == list( other.keys())) # checks that the list of keys for each matrix are equal - matrix_check = (self.matrix == np.array( + matrix_check = (self._matrix == np.array( [[other[key]] for key in self._keys])).all() # checks to see that each row matches return list_key_check and matrix_check list_key_check = self.keys() == other.keys() - matrix_check = (self.matrix == other.matrix).all() + matrix_check = (self._matrix == other.matrix).all() return list_key_check and matrix_check def __eq__(self, other: "DictLikeMatrixWrapper") -> bool: @@ -143,7 +144,7 @@ def __hash__(self): returns hash value sum for keys and matrix """ warn('hash will be deprecated after version 1.5 of ProgPy, will be replace with pandas.util.hash_pandas_object.', DeprecationWarning, stacklevel=2) - return hash(self.keys) + hash(self.matrix) + return hash(self.keys) + hash(self._matrix) def __str__(self) -> str: """ @@ -163,7 +164,7 @@ def copy(self) -> "DictLikeMatrixWrapper": """ creates copy of object """ - return DictLikeMatrixWrapper(self._keys, self.matrix.copy()) + return DictLikeMatrixWrapper(self._keys, self._matrix.copy()) def keys(self) -> list: """ @@ -176,19 +177,20 @@ def values(self) -> np.array: returns array of matrix values """ warn("After v1.5, values will be a property instead of a function.", DeprecationWarning, stacklevel=2) - if len(self.matrix) > 0 and len( - self.matrix[0]) == 1: # if the first row of the matrix has one value (i.e., non-vectorized) - return np.array([value[0] for value in self.matrix]) # the value from the first row - return self.matrix # the matrix (vectorized case) + if len(self._matrix) > 0 and len( + self._matrix[0]) == 1: # if the first row of the matrix has one value (i.e., non-vectorized) + return np.array([value[0] for value in self._matrix]) # the value from the first row + return self._matrix # the matrix (vectorized case) def items(self) -> zip: """ returns keys and values as a list of tuples (for iterating) """ - if len(self.matrix) > 0 and len( - self.matrix[0]) == 1: # first row of the matrix has one value (non-vectorized case) - return zip(self._keys, np.array([value[0] for value in self.matrix])) - return zip(self._keys, self.matrix) + # Disable deprecation warnings for internal progpy code. + if len(self._matrix) > 0 and len( + self._matrix[0]) == 1: # first row of the matrix has one value (non-vectorized case) + return zip(self._keys, np.array([value[0] for value in self._matrix])) + return zip(self._keys, self._matrix) def update(self, other: "DictLikeMatrixWrapper") -> None: """ @@ -201,7 +203,7 @@ def update(self, other: "DictLikeMatrixWrapper") -> None: else: # else it isn't it is appended to self._keys list # A new key! self._keys.append(key) - self.matrix = np.vstack((self.matrix, np.array([other[key]]))) + self._matrix = np.vstack((self._matrix, np.array([other[key]]))) def __contains__(self, key: str) -> bool: """ @@ -222,10 +224,10 @@ def __repr__(self) -> str: returns: a string of dictionaries containing all the keys and associated matrix values """ - if len(self.matrix) > 0 and len( - self.matrix[0]) == 1: # the matrix has rows and the first row/list has one value in it - return str({key: value[0] for key, value in zip(self._keys, self.matrix)}) - return str(dict(zip(self._keys, self.matrix))) + if len(self._matrix) > 0 and len( + self._matrix[0]) == 1: # the matrix has rows and the first row/list has one value in it + return str({key: value[0] for key, value in zip(self._keys, self._matrix)}) + return str(dict(zip(self._keys, self._matrix))) InputContainer = DictLikeMatrixWrapper diff --git a/src/progpy/utils/parameters.py b/src/progpy/utils/parameters.py index 10c716c..763fd95 100644 --- a/src/progpy/utils/parameters.py +++ b/src/progpy/utils/parameters.py @@ -1,6 +1,7 @@ # Copyright © 2021 United States Government as represented by the Administrator of the # National Aeronautics and Space Administration. All Rights Reserved. +from warnings import catch_warnings, simplefilter from collections import UserDict, abc from copy import deepcopy import json @@ -9,6 +10,7 @@ from scipy.integrate import OdeSolver import types + from progpy.utils.containers import DictLikeMatrixWrapper from progpy.utils.next_state import next_state_functions, SciPyIntegrateNextState from progpy.utils.noise_functions import measurement_noise_functions, process_noise_functions @@ -143,18 +145,24 @@ def __setitem__(self, key: str, value: float, _copy: bool = False) -> None: if 'process_noise_dist' in self and self['process_noise_dist'].lower() not in process_noise_functions: raise ValueError(f"Unsupported process noise distribution {self['process_noise_dist']}") - if all(value == 0 for value in self['process_noise'].values()): - # No noise, use none function - fcn = process_noise_functions['none'] - self._m.apply_process_noise = types.MethodType(fcn, self._m) - elif 'process_noise_dist' in self: - fcn = process_noise_functions[self['process_noise_dist'].lower()] - self._m.apply_process_noise = types.MethodType(fcn, self._m) - else: - # Default to gaussian - fcn = process_noise_functions['gaussian'] - self._m.apply_process_noise = types.MethodType(fcn, self._m) + # Disable deprecation warnings for internal progpy code. + with catch_warnings(): + simplefilter("ignore", DeprecationWarning) + + if all(value == 0 for value in self['process_noise'].values()): + # No noise, use none function + fcn = process_noise_functions['none'] + self._m.apply_process_noise = types.MethodType(fcn, self._m) + elif 'process_noise_dist' in self: + fcn = process_noise_functions[self['process_noise_dist'].lower()] + self._m.apply_process_noise = types.MethodType(fcn, self._m) + else: + # Default to gaussian + fcn = process_noise_functions['gaussian'] + self._m.apply_process_noise = types.MethodType(fcn, self._m) + #resetwarnings() + # Make sure every key is present # (single value already handled above) for key in self._m.states: @@ -186,18 +194,24 @@ def __setitem__(self, key: str, value: float, _copy: bool = False) -> None: if 'measurement_noise_dist' in self and self['measurement_noise_dist'].lower() not in measurement_noise_functions: raise ValueError(f"Unsupported measurement noise distribution {self['measurement_noise_dist']}") - if all(value == 0 for value in self['measurement_noise'].values()): - # No noise, use none function - fcn = measurement_noise_functions['none'] - self._m.apply_measurement_noise = types.MethodType(fcn, self._m) - elif 'measurement_noise_dist' in self: - fcn = measurement_noise_functions[self['measurement_noise_dist'].lower()] - self._m.apply_measurement_noise = types.MethodType(fcn, self._m) - else: - # Default to gaussian - fcn = measurement_noise_functions['gaussian'] - self._m.apply_measurement_noise = types.MethodType(fcn, self._m) - + # Disable deprecation warnings for internal progpy code. + with catch_warnings(): + simplefilter("ignore", category=DeprecationWarning) + + if all(value == 0 for value in self['measurement_noise'].values()): + # No noise, use none function + fcn = measurement_noise_functions['none'] + self._m.apply_measurement_noise = types.MethodType(fcn, self._m) + elif 'measurement_noise_dist' in self: + fcn = measurement_noise_functions[self['measurement_noise_dist'].lower()] + self._m.apply_measurement_noise = types.MethodType(fcn, self._m) + else: + # Default to gaussian + fcn = measurement_noise_functions['gaussian'] + self._m.apply_measurement_noise = types.MethodType(fcn, self._m) + + #resetwarnings() + # Make sure every key is present # (single value already handled above) if not all([key in self['measurement_noise'] for key in self._m.outputs]):