Examples

Plotting Experiments onto Multiple Axes

In order to allow for generated more complicated figures, the plotExpt function supports passing an instance matplotlib.pyplot.Axes object.

import DAPyr as dap
import matplotlib.pyplot as plt
expt = dap.Expt('Plotting_example', {'expt_flag': 0, 'model_flag': 0, 'T': 200, 'seed': 1})
dap.runDA(expt)

plt.close()
#Create a Figure and Axes instance, make sure to specify a 3d projection
fig, axes = plt.subplots(1, 2, subplot_kw = {'projection': '3d'})
T1, T2 = 10, 150
dap.plotExpt(expt, T = T1, ax = axes[0])
dap.plotExpt(expt, T = T2, ax = axes[1])
axes[0].set_title('Experiment at time T = {}'.format(T1))
axes[1].set_title('Experiment at time T = {}'.format(T2))

#You many then modify the Axes instance to adjust for axes limits
new_xlim = (-9.5, -7.0)
new_ylim = (-9.5, -6.0)
new_zlim = (24, 30)
for ax in axes:
      ax.set_xlim(new_xlim)
      ax.set_ylim(new_ylim)
      ax.set_zlim(new_zlim)
plt.show()
Figure with multiple plotExpt instances

A figure with multiple plotExpt instances at different time steps in the experiment.

Ensuring Same Starting State between Experiments

When setting up experiments, you may want to ensure that two experiments with different parameter configuration have the same states. As in, the same model truth (\(x_t\)), observations (\(Y\)), and initial ensemble state (\(x_f^0\)).

Using the seed parameter

The seed parameter in the Expt class sets the seed of the random number generator used to spin up the initial ensemble state, \(x_f^0\).

import DAPyr as dap
import numpy as np
expt1 = dap.Expt('enkf_run', {'expt_flag': 0, 'Ne': 15, 'seed': 10})
expt2 = dap.Expt('lpf_run', {'expt_flag': 1, 'Ne': 15, 'seed': 10})
np.allclose(expt1.getParam('xf_0'), expt2.getParam('xf_0'))
True

Note

Setting the seed parameter will only ensure equal ensemble initial states if ensemble sizes are equal between experiments. Additionally, the seed parameter does not enfore equality for either model truth or observation state vectors.

Using the copyStates method

The copyStates method ensures all three state vectors are copied from another experiment. However, one must be careful when copying states to another experiment with different modified parameters, as many parameters directly influence the state vectors. Major differences between experiment will be caught and raise exceptions. For example, attempting to copy the state vectors from an experiment where h_flag = 0 to an experiment with h_flag = 1 will throw an exception. On the contrary, copying the state vectors from an experiment where l05_I = 1 to an experiment where l05_I = 12 will result in incorrect model integration.

A graph showcasing state vector dependencies on parameter

State vector dependency based on parameter. Edges point to what parameters influence what state vectors during spinup.

import DAPyr as dap
import numpy as np
expt1 = dap.Expt('enkf_run', {'expt_flag': 0, 'Ne': 15})
expt2 = dap.Expt('lpf_run', {'expt_flag': 1, 'Ne': 15})
np.allclose(expt1.getParam('xf_0'), expt2.getParam('xf_0'))
False
#Copy states of expt1 onto expt2
expt2.copyStates(expt1)
np.allclose(expt1.getParam('xf_0'), expt2.getParam('xf_0'))
True
np.allclose(expt1.getParam('xt'), expt2.getParam('xt'))
True
np.allclose(expt1.getParam('Y'), expt2.getParam('Y'))
True

Directly modifying the Expt.states attribute

For more complex modifications and edit you can directly access the state vectors through the Expt.states attribute. The states attribute is a dictionary containing the model truth (xt), observations (Y), and initial ensemble state (xf_0).

import DAPyr as dap
import numpy as np
expt = dap.Expt('enkf_run', {'expt_flag': 0, 'Ne': 15})

#Add additional noise to initial ensemble state vector
Nx, Ne = expt.states['xf_0'].shape
expt.states['xf_0'] = expt.states['xf_0'] + np.random.randn(Nx, Ne)