Kalman Filters#

This module implements several variants of the Kalman Filter (KF) data assimilation (inversion/inferencce) scheme. The filter consists of two steps; namely forecast (prediction) and analysis (correction). In the former, the model integrates (propagates) the model state forward in time, and in the latter, an observation is used to update/correct the model state at that observation time given the associated noise models.

class KalmanFilterConfigs(*, debug=False, verbose=False, output_dir='./_PYOED_RESULTS_', name='KF: Vanilla Kalman Filtering', model=None, prior=None, observation_error_model=None, observation_operator=None, observations=None, optimizer=None, optimizer_configs=None)[source]#

Bases: BayesianFilterConfigs

Configurations class for the KalmanFilter class.

Parameters:
  • verbose (bool) – a boolean flag to control verbosity of the object.

  • debug (bool) – a boolean flag that enables adding extra functionlity in a debug mode

  • output_dir (str | Path) – the base directory where the output files will be saved.

  • model (None | SimulationModel) – the simulation model.

  • prior (None | ErrorModel) – Background/Prior model (e.g., GaussianErrorModel)

  • observation_operator (None | ObservationOperator) – operator to map model state to observation space

  • observation_error_model (None | ErrorModel) – Observation error model (e.g., GaussianErrorModel)

  • observations (None | Any) – Observational data (the data type is very much dependent of the DA method)

  • optimizer (None | Optimizer) –

    the optimization routine (optimizer) to be registered and later used for solving the OED problem. This can be one of the following:

    • None: In this case, no optimizer is registered, and the solve() won’t be functional until an optimization routine is registered.

    • An optimizer instance (object that inherits :py:class`Optimizer`). In this case, the optimizer is registered as is and is updated with the passed configurations if available.

    • The class (subclass of Optimizer) to be used to instantiate the optimizer.

  • optimizer_configs (None | dict | OptimizerConfigs) –

    the configurations of the optimization routine. This can be one of the following:

    • None, in this case configurations are discarded, and whatever default configurations of the selected/passed optimizer are employed.

    • A dict holding full/partial configurations of the selected optimizer. These are either used to instantiate or update the optimizer configurations based on the type of the passed optimizer.

    • A class providing implementations of the configurations (this must be a subclass of OptimizerConfigs.

    • An instance of a subclass of OptimizerConfigs which is to set/udpate optimizer configurations.

    Note

    Not all DA (inverse problem) objects are optimization-based. For example, particle-based (EnKF, PF, etc.) employ a sample to estimate the flow of the distribution through the model dynamics (prior -> posterior). Thus, the optimizer (and configs) in this case (the default) are set to None. For optimization-based methods such as 3DVar, 4DVar, etc., an optimizer must be registered for the inverse problem to be solved.

  • name (str | None) – Name of the filter

__init__(*, debug=False, verbose=False, output_dir='./_PYOED_RESULTS_', name='KF: Vanilla Kalman Filtering', model=None, prior=None, observation_error_model=None, observation_operator=None, observations=None, optimizer=None, optimizer_configs=None)#
class KalmanFilter(configs=None)[source]#

Bases: BayesianFilter

A class implementing the vanilla Kalman Filtering (KF) scheme for state inference/inversion, assuming the model equation is on the form :math:` mathbf{x}_{i+1}=mathcal(M) mathbf{x}_{i}`, and \(\mathbf{x}_{i}\) is the model state at ith time instance/step.

Standard KF inversion/filtering retrieves model state from noisy observations.

This version is very elementary and is developed as guidelines to create more advanced versions:

  • Here, the filter works by applying ‘analysis/correction’ step to registered prior based on the registered observation.

  • The analysis step creates a Gaussian posterior which can be used to make future forecasts/prediction (which generates a prior at a future time step).

This scheme assumes linear models and Gaussian observational noise. The inference/inversion (unknown) state is regularized by a Gaussian Prior, which is equivalent to 3DVar schemes given the linear-Gaussian assumption holds.

You can either pass the KF elements upon initialization, or later using the proper register methods. However, you can’t use solve() before registering all proper elements (simulation model, prior, observations/data, and observation operator).

Note

  • The KF scheme assumes the dynamical model and the observational operator

    are both specified.

  • A necessary requirement here is that both the dynamical model and the

    observation operator are both linear, otherwise results are not expected to be good.

  • The prior and the observation error model are both Gaussian

__init__(configs=None)[source]#
validate_configurations(configs, raise_for_invalid=True)[source]#

Validate passed configurations.

Parameters:

configs (dict | KalmanFilterConfigs) – configurations to validate. If a KalmanFilterConfigs object is passed, validation is performed on the entire set of configurations. However, if a dictionary is passed, validation is performed only on the configurations corresponding to the keys in the dictionary.

register_model(model=None)[source]#

Register (and return) the simulation model to be registered. This calls InverseProblem.register_model and adds extra assertions/functionality specific for filters.

Raises:

TypeError – if the type of passed model is not supported

register_prior(prior=None, initiate_posterior=True)[source]#

Update prior/regularization information. Since, changing the prior implies a different posterior, the argument initiate_posterior is added with defaul value True to make sure the posterio is overwritten/reset

Raises:

TypeError is raised if:

  • the passed prior type is not supported

  • a valid simulation model has not been registered yet

  • the prior is not compatible with the registered simulation model

Note

The prior here is asserted on the model state.

forecast(tspan, posterior=None)[source]#

Apply the forecast/prediction step of the filter (simulate state over a timespan). This is carried out by propagating the posteiror/analysis distribution including mean and covariance matrix over the passed prediction timespan (t0, tf).

Parameters:
  • tspan (tuple) – (t0, tf) defining the forecast timespan. The analysis/posterior is supposed to be defined at t0, and the forecast (prediction) is evaluated at tf.

  • posterior (GaussianErrorModel) – the posterior (yielding mean & covariance) used as starting point for prediction. If None, the internally saved posterior (if available) is used.

Returns:

the Gaussian forecast (GaussianErrorModel)

analysis(prior=None, update_posterior=False)[source]#
Analysis step of the (Vanilla Kalman) filter. This function uses the prior and

the registered observtion to evaluate/update the posterior (Gaussian in this case).

Parameters:

prior (GaussianErrorModel) – the prior (yielding mean & covariance) used as starting point for prediction. If None, the registerd prior (if available) is used.

Returns:

the Gaussian posterior model

solve(tspan, forecast_first=True, prior=None, posterior=None, update_posterior=True)[source]#

Solve the filtering problem over one assimilation cycle. Here, there are two options based on the value of forecast_first:

  • If forecast_first is True the posterior is first propagated over the timespan, and then the analysis is carried out

  • If forecast_first is False, the analysis is carried out first, and then the forecast over the timespan is made.

In both cases, this returns the distribution (posterior/prior) at the end of the assimilation cycle tspan.

Note

If forecast_first is True, the posterior at the begining of tspan is either passed to posterior or extracted from self. Similarily, if forecast_first is False, the prior at the begining of tspan is either passed to prior or extracted from self.

This module implements several variants of the Kalman Filter (KF) data assimilation (inversion/inferencce) scheme for complex-valued random variables.

class ConventionalComplexKalmanFilterConfigs(*, debug=False, verbose=False, output_dir='./_PYOED_RESULTS_', name='CCKF: Conventional Complex Valued Kalman Filter', model=None, prior=None, observation_error_model=None, observation_operator=None, observations=None, optimizer=None, optimizer_configs=None)[source]#

Bases: KalmanFilterConfigs

Configurations class for the ConventionalComplexKalmanFilter class. The configurations here are identical to the parent’s KalmanFilterConfigs except that the prior has to be a complex Gaussian distribution.

Parameters:
  • verbose (bool) – a boolean flag to control verbosity of the object.

  • debug (bool) – a boolean flag that enables adding extra functionlity in a debug mode

  • output_dir (str | Path) – the base directory where the output files will be saved.

  • model (None | SimulationModel) – the simulation model.

  • prior (None | ErrorModel) – Background/Prior model (e.g., GaussianErrorModel)

  • observation_operator (None | ObservationOperator) – operator to map model state to observation space

  • observation_error_model (None | ErrorModel) – Observation error model (e.g., GaussianErrorModel)

  • observations (None | Any) – Observational data (the data type is very much dependent of the DA method)

  • optimizer (None | Optimizer) –

    the optimization routine (optimizer) to be registered and later used for solving the OED problem. This can be one of the following:

    • None: In this case, no optimizer is registered, and the solve() won’t be functional until an optimization routine is registered.

    • An optimizer instance (object that inherits :py:class`Optimizer`). In this case, the optimizer is registered as is and is updated with the passed configurations if available.

    • The class (subclass of Optimizer) to be used to instantiate the optimizer.

  • optimizer_configs (None | dict | OptimizerConfigs) –

    the configurations of the optimization routine. This can be one of the following:

    • None, in this case configurations are discarded, and whatever default configurations of the selected/passed optimizer are employed.

    • A dict holding full/partial configurations of the selected optimizer. These are either used to instantiate or update the optimizer configurations based on the type of the passed optimizer.

    • A class providing implementations of the configurations (this must be a subclass of OptimizerConfigs.

    • An instance of a subclass of OptimizerConfigs which is to set/udpate optimizer configurations.

    Note

    Not all DA (inverse problem) objects are optimization-based. For example, particle-based (EnKF, PF, etc.) employ a sample to estimate the flow of the distribution through the model dynamics (prior -> posterior). Thus, the optimizer (and configs) in this case (the default) are set to None. For optimization-based methods such as 3DVar, 4DVar, etc., an optimizer must be registered for the inverse problem to be solved.

  • name (str | None) – Name of the filter

__init__(*, debug=False, verbose=False, output_dir='./_PYOED_RESULTS_', name='CCKF: Conventional Complex Valued Kalman Filter', model=None, prior=None, observation_error_model=None, observation_operator=None, observations=None, optimizer=None, optimizer_configs=None)#
class ConventionalComplexKalmanFilter(configs=None)[source]#

Bases: KalmanFilter

A class implementing the simplest version of Kalman Filtering (KF) scheme for complex-valued state inference/inversion, assuming the model equation is on the form :math:` mathbf{x}_{i+1}=mathcal(M) mathbf{x}_{i}`, and \(\,mathbf{x}_{i}\) is the model state at ith time instance/step.

Standard (conventional) complex-valued KF inversion/filtering retrieves model state from noisy observations. Unlike KalmanFilter, this class supports complex-valued states and models, that is both \(\mathbf{x}\) and \(\mathcal{M}\) are potentially complex-valued.

The observations \(\mathbf{y}\), however, in this implementation are real-valued.

Note

Everything here is similar to KalmanFilter except that transposes are replaced with transposed conjugets (Hermitian). This implicitly assumes proper signal (the random variable is proper), and thus, the pseudo-covariance matrix vanishes.

Note

  • The scheme assumes the dynamical model and the observational operator are both specified.

  • A necessary requirement here is that both the dynamical model and the

    observation operator are both linear, otherwise results are not expected to be good.

  • The prior must by complex-valued error-model (e.g., ComplexGaussianErrorModel).

    Thus, if a standard real-valued Gaussian prior (e.g., GaussianErrorModel) is passed, its moments will be used to create an instance of ComplexGaussianErrorModel with same mean, and covariance.

  • Pseudo-covariances are discarded here, and are not evaluated in the posterior (they are set to 0+0j in the returned complex Gaussian posterior).

  • It is up to the user to make sure these elements are propoperly specified (at least initially!)

__init__(configs=None)[source]#
validate_configurations(configs, raise_for_invalid=True)[source]#

Validate passed configurations.

Parameters:

configs (dict | ConventionalComplexKalmanFilterConfigs) – configurations to validate. If a ConventionalComplexKalmanFilterConfigs object is passed, validation is performed on the entire set of configurations. However, if a dictionary is passed, validation is performed only on the configurations corresponding to the keys in the dictionary.

register_prior(prior=None, initiate_posterior=True)[source]#

Update prior/regularization information. Since, changing the prior implies a different posterior, the argument initiate_posterior is added with defaul value True to make sure the posterio is overwritten/reset

Raises:

TypeError is raised if:

  • the passed prior type is not supported

  • a valid simulation model has not been registered yet

  • the prior is not compatible with the registered simulation model

Note

The prior here is asserted on the model state.

forecast(tspan, posterior=None)[source]#

Apply the forecast/prediction step of the filter (simulate state over a timespan). This is carried out by propagating the posteiror/analysis distribution including mean and covariance matrix over the passed prediction timespan (t0, tf).

Parameters:
  • tspan (tuple) – (t0, tf) defining the forecast timespan. The analysis/posterior is supposed to be defined at t0, and the forecast (prediction) is evaluated at tf.

  • posterior (GaussianErrorModel) – the posterior (yielding mean & covariance) used as starting point for prediction. If None, the internally saved posterior (if available) is used.

Returns:

the Gaussian forecast (GaussianErrorModel)

analysis(prior=None, update_posterior=False)[source]#
Analysis step of the (Vanilla Kalman) filter. This function uses the prior and

the registered observtion to evaluate/update the posterior (Gaussian in this case).

Parameters:

prior (GaussianErrorModel) – the prior (yielding mean & covariance) used as starting point for prediction. If None, the registerd prior (if available) is used.

Returns:

the Gaussian posterior model

class AugmentedComplexKalmanFilterConfigs(*, debug=False, verbose=False, output_dir='./_PYOED_RESULTS_', name='ACKF: Augmented Complex Valued Kalman Filter', model=None, prior=None, observation_error_model=None, observation_operator=None, observations=None, optimizer=None, optimizer_configs=None)[source]#

Bases: ConventionalComplexKalmanFilterConfigs

Configurations class for the AugmentedComplexKalmanFilter class. The configurations here are identical to the parent’s ConventionalComplexKalmanFilterConfigs except for the name.

Parameters:
  • verbose (bool) – a boolean flag to control verbosity of the object.

  • debug (bool) – a boolean flag that enables adding extra functionlity in a debug mode

  • output_dir (str | Path) – the base directory where the output files will be saved.

  • model (None | SimulationModel) – the simulation model.

  • prior (None | ErrorModel) – Background/Prior model (e.g., GaussianErrorModel)

  • observation_operator (None | ObservationOperator) – operator to map model state to observation space

  • observation_error_model (None | ErrorModel) – Observation error model (e.g., GaussianErrorModel)

  • observations (None | Any) – Observational data (the data type is very much dependent of the DA method)

  • optimizer (None | Optimizer) –

    the optimization routine (optimizer) to be registered and later used for solving the OED problem. This can be one of the following:

    • None: In this case, no optimizer is registered, and the solve() won’t be functional until an optimization routine is registered.

    • An optimizer instance (object that inherits :py:class`Optimizer`). In this case, the optimizer is registered as is and is updated with the passed configurations if available.

    • The class (subclass of Optimizer) to be used to instantiate the optimizer.

  • optimizer_configs (None | dict | OptimizerConfigs) –

    the configurations of the optimization routine. This can be one of the following:

    • None, in this case configurations are discarded, and whatever default configurations of the selected/passed optimizer are employed.

    • A dict holding full/partial configurations of the selected optimizer. These are either used to instantiate or update the optimizer configurations based on the type of the passed optimizer.

    • A class providing implementations of the configurations (this must be a subclass of OptimizerConfigs.

    • An instance of a subclass of OptimizerConfigs which is to set/udpate optimizer configurations.

    Note

    Not all DA (inverse problem) objects are optimization-based. For example, particle-based (EnKF, PF, etc.) employ a sample to estimate the flow of the distribution through the model dynamics (prior -> posterior). Thus, the optimizer (and configs) in this case (the default) are set to None. For optimization-based methods such as 3DVar, 4DVar, etc., an optimizer must be registered for the inverse problem to be solved.

  • name (str | None) – Name of the filter

__init__(*, debug=False, verbose=False, output_dir='./_PYOED_RESULTS_', name='ACKF: Augmented Complex Valued Kalman Filter', model=None, prior=None, observation_error_model=None, observation_operator=None, observations=None, optimizer=None, optimizer_configs=None)#
class AugmentedComplexKalmanFilter(configs=None)[source]#

Bases: ConventionalComplexKalmanFilter

A class implementing the augmented version of Kalman Filtering (KF) scheme for complex-valued state inference/inversion, assuming the model equation is on the form :math:` mathbf{x}_{i+1}=mathcal(M) mathbf{x}_{i}`, and \(\,mathbf{x}_{i}\) is the model state at ith time instance/step.

Note

This implementation relies on the augmented statistics, and incorporates both covariances and pseudo-covariances.

Note

  • The scheme assumes the dynamical model and the observational operator are both specified.

  • A necessary requirement here is that both the dynamical model and the

    observation operator are both linear, otherwise results are not expected to be good.

  • The prior must by complex-valued error-model (e.g., ComplexGaussianErrorModel).

    Thus, if a standard real-valued Gaussian prior (e.g., GaussianErrorModel) is passed, its moments will be used to create an instance of ComplexGaussianErrorModel with same mean, and covariance.

  • Pseudo-covariances are incoporated here, and are thus part of the posterior.

  • It is up to the user to make sure these elements are propoperly specified (at least initially!)

__init__(configs=None)[source]#
forecast(tspan, posterior=None)[source]#

Apply the forecast/prediction step of the filter (simulate state over a timespan). This is carried out by propagating the posteiror/analysis distribution including mean and covariance matrix over the passed prediction timespan (t0, tf).

Parameters:
  • tspan (tuple) – (t0, tf) defining the forecast timespan. The analysis/posterior is supposed to be defined at t0, and the forecast (prediction) is evaluated at tf.

  • posterior (GaussianErrorModel) – the posterior (yielding mean & covariance) used as starting point for prediction. If None, the internally saved posterior (if available) is used.

Returns:

the Gaussian forecast (GaussianErrorModel)

analysis(prior=None, update_posterior=False)[source]#
Analysis step of the (Vanilla Kalman) filter. This function uses the prior and

the registered observtion to evaluate/update the posterior (Gaussian in this case).

Parameters:

prior (GaussianErrorModel) – the prior (yielding mean & covariance) used as starting point for prediction. If None, the registerd prior (if available) is used.

Returns:

the Gaussian posterior model