<jupyter_start><jupyter_text>Beer cooling exampleAt time t=0, a glass of beer is dropped to a bucket of cold water with given temperature. Beer is cooled by water and heated with the outside air that is at a given temperature. Beer temperature is measured every minute, and the goal is to infer the heat transfer coefficients through the glass and air, plus the model and observation noise standard deviations.We write the model as the following DLM system:  1) Define the functions that build the needed matricesHere, we write a Stan functions block that builds the matrices given the parameters. Note that the noise parameters are separated from the "other" parameters so that we can assign priors separately for them (e.g. enforce positivity).<jupyter_code>beer_functions = """
functions {
    matrix build_A(vector theta) {
        matrix[1,1] A;
        A[1,1] = 1-theta[1]-theta[2];
        return A;
    }
    matrix build_B(vector theta) {
        matrix[1,2] B;
        B[1,1] = theta[1];
        B[1,2] = theta[2];
        return B;
    }
    matrix build_C(vector theta) {
        matrix[1,1] C;
        C[1,1] = 1;
        return C;
    }
    matrix build_Q(vector noise_theta) {
        matrix[1,1] Q;
        Q[1,1] = square(noise_theta[1]);
        return Q;
    }
    matrix build_R(vector noise_theta) {
        matrix[1,1] R;
        R[1,1] = square(noise_theta[2]);
        return R;
    }
}
"""<jupyter_output><empty_output><jupyter_text>2) Compile the code with `CmdStanPy`First, we read the general DLM stan code and append the user-defined functions to the model file.<jupyter_code>dlm_code = Path('../dlm.stan').read_text()
Path('beer.stan').write_text(beer_functions + dlm_code);
beer_model = CmdStanModel(stan_file='beer.stan')<jupyter_output><empty_output><jupyter_text>3) Construct the dataThe general DLM code always needs the same input data variables. Note that the vectors and matrices need to be given as python lists so that the serialization to JSON works.<jupyter_code>y = [28, 24, 20, 17.5, 15.5, 13.5, 12, 11, 10]

beer_data = {
    'N_obs': len(y),
    'N_theta': 2,
    'N_noise_theta': 2,
    'state_dim': 1,
    'input_dim': 2,
    'obs_dim': 1,
    'Y_obs': [[yi] for yi in y],
    'U_obs': len(y)*[[5, 23]],
    'm0': [31.0],
    'P0': [[1**2]],
    'theta_mu': [0, 0],
    'theta_Sig': [[10**2, 0],[0, 10**2]],
    'noise_mu': [0.2, 0.2],
    'noise_Sig': [[0.2**2, 0], [0, 0.2**2]]
}
with open('beer_data.json', 'w') as f:
    json.dump(beer_data, f)<jupyter_output><empty_output><jupyter_text>4) Fit the model with HMCSave the output files to a separate output folder to keep things clean. Print the fit object to get some details about the files that were produced.<jupyter_code>beer_fit = beer_model.sample(data='beer_data.json', output_dir='output')
print(beer_fit)<jupyter_output><empty_output><jupyter_text>5) Access the parameters and plot resultsLet us draw the sampled states and parameters. Sampled parameters can be accessed with `CmdStanPy`:s helper `stan_variable`.<jupyter_code>draws_noise = beer_fit.stan_variable(name='noise_theta')
draws_theta = beer_fit.stan_variable(name='theta')
draws_x = beer_fit.stan_variable(name='x_samples')
plt.figure(figsize=(7,4))

plt.plot(range(len(y)), draws_x[0::10,:,0].T, c='0.5', alpha=0.2)
plt.plot(range(len(y)), np.quantile(draws_x[0:,:,0].T, [0.025, 0.975], axis=1).T, 'k--')
plt.plot(range(len(y)), np.quantile(draws_x[0:,:,0].T, 0.5, axis=1), 'k-')
plt.plot(range(len(y)), y, 'r.')

plt.grid(True)
plt.show()
pd.plotting.scatter_matrix(pd.DataFrame(draws_theta));
pd.plotting.scatter_matrix(pd.DataFrame(draws_noise));<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.14043252121543937, 'fraction_numerical': 0.03284971256501506, 'mean_word_length': 4.227467811158799, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '659040', 'license': 'MIT', 'n_tokens_mistral': 1378, 'n_tokens_neox': 1299, 'n_words': 368, 'path': 'examples/stan_dlm_beer.ipynb', 'repo_name': 'solbes/dlmstan', 'size': '3653'}