CNModel Tutorial

Trey V. Wenger (c) April 2025

Here we demonstrate the basic features of the CNModel model. The CNModel models the hyperfine spectral structure of \({\rm CN}\) and \(^{13}{\rm CN}\) including non-LTE effects. Please review the bayes_spec documentation and tutorials for a more thorough description of the steps outlined in this tutorial: https://bayes-spec.readthedocs.io/en/stable/index.html

[1]:
# General imports
import os
import pickle
import time

import matplotlib.pyplot as plt
import arviz as az
import pandas as pd
import numpy as np
import pymc as pm

print("arviz version:", az.__version__)

print("pymc version:", pm.__version__)

import bayes_spec
print("bayes_spec version:", bayes_spec.__version__)

import bayes_cn_hfs
print("bayes_cn_hfs version:", bayes_cn_hfs.__version__)

# Notebook configuration
pd.options.display.max_rows = None
arviz version: 0.22.0dev
pymc version: 5.21.1
bayes_spec version: 1.7.8
bayes_cn_hfs version: 2.0.0-staging+0.g7afe3a8.dirty

supplement_mol_data

Here we model the hyperfine structure of CN emission. We use the helper function supplement_mol_data to download the molecular data for this molecule.

[2]:
from bayes_cn_hfs import supplement_mol_data

mol_data_12CN, mol_weight_12CN = supplement_mol_data("CN")
print(mol_data_12CN.keys())
print("transition frequency (MHz):", mol_data_12CN['freq'])
print("Einstein A coefficient (s-1):", mol_data_12CN['Aul'])
print("Upper state degrees of freedom:", mol_data_12CN['degu'])
print("Lower state energy level (erg)", mol_data_12CN['El'])
print("Upper state energy level (erg)", mol_data_12CN['Eu'])
print("Relative intensities", mol_data_12CN['relative_int'])
print("Partition function terms:", mol_data_12CN["log10_Q_terms"])
print("Upper state quantum numbers:", mol_data_12CN["Qu"])
print("lower states quantum numbers", mol_data_12CN["Ql"])
print("state info", mol_data_12CN["states"])
dict_keys(['freq', 'Aul', 'degu', 'El', 'Eu', 'relative_int', 'log10_Q_terms', 'Qu', 'Ql', 'states', 'state_u_idx', 'state_l_idx', 'Gu', 'Gl'])
transition frequency (MHz): [113123.3687 113144.19   113170.535  113191.325  113488.142  113490.985
 113499.643  113508.934  113520.4215]
Einstein A coefficient (s-1): [1.26969616e-06 1.03939111e-05 5.07869910e-06 6.59525390e-06
 6.64784064e-06 1.17706070e-05 1.04919208e-05 5.12459350e-06
 1.28243028e-06]
Upper state degrees of freedom: [2 2 4 4 4 6 2 4 2]
Lower state energy level (erg) [1.3905121e-19 0.0000000e+00 1.3905121e-19 0.0000000e+00 1.3905121e-19
 0.0000000e+00 1.3905121e-19 0.0000000e+00 0.0000000e+00]
Upper state energy level (erg) [7.49702428e-16 7.49701340e-16 7.50014955e-16 7.50013660e-16
 7.52119441e-16 7.51999228e-16 7.52195648e-16 7.52118159e-16
 7.52194276e-16]
Relative intensities [0.01204699 0.09860036 0.09633376 0.1250773  0.12574146 0.33394774
 0.09921527 0.09691221 0.01212491]
Partition function terms: [0.40307694 0.97433601]
Upper state quantum numbers: [np.str_('1 0 1 1'), np.str_('1 0 1 1'), np.str_('1 0 1 2'), np.str_('1 0 1 2'), np.str_('1 0 2 2'), np.str_('1 0 2 3'), np.str_('1 0 2 1'), np.str_('1 0 2 2'), np.str_('1 0 2 1')]
lower states quantum numbers [np.str_('0 0 1 1'), np.str_('0 0 1 2'), np.str_('0 0 1 1'), np.str_('0 0 1 2'), np.str_('0 0 1 1'), np.str_('0 0 1 2'), np.str_('0 0 1 1'), np.str_('0 0 1 2'), np.str_('0 0 1 2')]
state info {'state': [np.str_('0 0 1 1'), np.str_('0 0 1 2'), np.str_('1 0 1 1'), np.str_('1 0 1 2'), np.str_('1 0 2 1'), np.str_('1 0 2 2'), np.str_('1 0 2 3')], 'deg': array([2, 4, 2, 4, 2, 4, 6]), 'E': array([1.00714381e-03, 0.00000000e+00, 5.43007258e+00, 5.43233621e+00,
       5.44813090e+00, 5.44757894e+00, 5.44670824e+00])}

Simulating Data

To test the model, we must simulate some data. We can do this with CNModel, but we must pack a “dummy” data structure first.

[3]:
from bayes_spec import SpecData

# spectral axis definition
freq_axis_1 = np.arange(113100.0, 113210.0, 0.2) # MHz
freq_axis_2 = np.arange(113470.0, 113530.0, 0.2) # MHz

# data noise can either be a scalar (assumed constant noise across the spectrum)
# or an array of the same length as the data
noise = 0.03 # K

# brightness data. In this case, we just throw in some random data for now
# since we are only doing this in order to simulate some actual data.
brightness_data_1 = noise * np.random.randn(len(freq_axis_1)) # K
brightness_data_2 = noise * np.random.randn(len(freq_axis_2)) # K

# CNModel datasets can be named anything, here we name them "12CN-1" and "12CN-2"
obs_1 = SpecData(
    freq_axis_1,
    brightness_data_1,
    noise,
    xlabel=r"LSRK Frequency (MHz)",
    ylabel=r"$T_B$ (K)",
)
obs_2 = SpecData(
    freq_axis_2,
    brightness_data_2,
    noise,
    xlabel=r"LSRK Frequency (MHz)",
    ylabel=r"$T_B$ (K)",
)
dummy_data = {"12CN-1": obs_1, "12CN-2": obs_2}

# Plot the simulated data
fig, axes = plt.subplots(2)
axes[0].plot(dummy_data["12CN-1"].spectral, dummy_data["12CN-1"].brightness, "k-")
axes[0].set_ylabel(dummy_data["12CN-1"].ylabel)
axes[1].plot(dummy_data["12CN-2"].spectral, dummy_data["12CN-2"].brightness, "k-")
axes[1].set_xlabel(dummy_data["12CN-2"].xlabel)
_ = axes[1].set_ylabel(dummy_data["12CN-2"].ylabel)
../_images/notebooks_cn_model_5_0.png

Now that we have a dummy data format, we can generate a simulated observation by evaluating the model for a given set of parameters.

[4]:
from bayes_cn_hfs.cn_model import CNModel

# Initialize and define the model
n_clouds = 3 # number of cloud components
baseline_degree = 2 # polynomial baseline degree
model = CNModel(
    dummy_data,
    molecule="CN", # molecule (either "CN" or "13CN")
    mol_data=mol_data_12CN, # molecular data
    bg_temp = 2.7, # assumed background temperature (K)
    Beff = 1.0, # beam efficiency
    Feff = 1.0, # forward efficiency
    n_clouds=n_clouds,
    baseline_degree=baseline_degree,
    seed=1234,
    verbose=True
)
model.add_priors(
    prior_log10_N = [13.5, 1.0], # mean and width of log10 total column density prior (cm-2)
    prior_log10_Tkin = [1.0, 0.5], # mean and width of log10 kinetic temperature prior (K)
    prior_velocity = [0.0, 5.0], # mean and width of velocity prior (km/s)
    prior_fwhm_nonthermal = 1.0, # width of non-thermal broadening prior (km/s)
    prior_fwhm_L = None, # assume Gaussian line profile
    prior_rms = None, # do not infer spectral rms
    prior_baseline_coeffs = None, # use default baseline priors
    assume_LTE = True, # assume kinetic temperature = excitation temperature
    prior_log10_Tex = None, # ignored for this LTE model
    assume_CTEX = True, # assume CTEX
    prior_log10_LTE_precision = None, # ignored for this LTE model
    fix_log10_Tkin = None, # do not fix the kinetic temperature
    clip_weights = 1.0e-9, # clip statistical weights between [clip_weights, 1-clip_weights]
    clip_tau = -10.0, # clip optical depths below to prevent masers
    ordered = False, # do not assume optically-thin
)
model.add_likelihood()

sim_params = {
    "log10_N": [13.8, 13.9, 14.0],
    "log10_Tkin": [0.65, 0.6, 0.5],
    "fwhm_nonthermal": [1.0, 1.25, 1.5],
    "velocity": [-2.0, 0.0, 2.5],
    "fwhm_L": 0.0,
    "baseline_12CN-1_norm": [-2.0, -5.0, 8.0],
    "baseline_12CN-2_norm": [4.0, -2.0, 5.0],
}

# add derived quantities to sim_params
for key in model.cloud_deterministics:
    if key not in sim_params.keys():
        sim_params[key] = model.model[key].eval(sim_params, on_unused_input="ignore")

# Evaluate and save simulated observations
sim_obs1 = model.model["12CN-1"].eval(sim_params, on_unused_input="ignore")
sim_obs2 = model.model["12CN-2"].eval(sim_params, on_unused_input="ignore")

# Plot the simulated data
fig, axes = plt.subplots(2)
axes[0].plot(dummy_data["12CN-1"].spectral, sim_obs1, "k-")
axes[0].set_ylabel(dummy_data["12CN-1"].ylabel)
axes[1].plot(dummy_data["12CN-2"].spectral, sim_obs2, "k-")
axes[1].set_xlabel(dummy_data["12CN-2"].xlabel)
_ = axes[1].set_ylabel(dummy_data["12CN-2"].ylabel)
../_images/notebooks_cn_model_7_0.png
[5]:
sim_params
[5]:
{'log10_N': [13.8, 13.9, 14.0],
 'log10_Tkin': [0.65, 0.6, 0.5],
 'fwhm_nonthermal': [1.0, 1.25, 1.5],
 'velocity': [-2.0, 0.0, 2.5],
 'fwhm_L': 0.0,
 'baseline_12CN-1_norm': [-2.0, -5.0, 8.0],
 'baseline_12CN-2_norm': [4.0, -2.0, 5.0],
 'fwhm_thermal': array([0.08867757, 0.08371703, 0.07461288]),
 'fwhm': array([1.00392416, 1.25280028, 1.50185455]),
 'log10_Tex_ul': array([0.65, 0.6 , 0.5 ]),
 'LTE_weights': array([[0.17659718, 0.353274  , 0.05237634, 0.10469961, 0.05216502,
         0.10434294, 0.15654492],
        [0.18885791, 0.37781138, 0.04829246, 0.09653001, 0.04807389,
         0.09616112, 0.14427323],
        [0.21685988, 0.43385792, 0.0389559 , 0.07785605, 0.03873407,
         0.07748167, 0.11625451]]),
 'Tex': array([[4.46683592, 3.98107171, 3.16227766],
        [4.46683592, 3.98107171, 3.16227766],
        [4.46683592, 3.98107171, 3.16227766],
        [4.46683592, 3.98107171, 3.16227766],
        [4.46683592, 3.98107171, 3.16227766],
        [4.46683592, 3.98107171, 3.16227766],
        [4.46683592, 3.98107171, 3.16227766],
        [4.46683592, 3.98107171, 3.16227766],
        [4.46683592, 3.98107171, 3.16227766]]),
 'tau': array([[0.02780937, 0.03961643, 0.06312223],
        [0.22764058, 0.32429648, 0.51673788],
        [0.2223333 , 0.31672379, 0.5046276 ],
        [0.28871089, 0.41128963, 0.65532851],
        [0.28981529, 0.41280405, 0.65753902],
        [0.76986139, 1.09659601, 1.7468342 ],
        [0.22866526, 0.32570236, 0.51879336],
        [0.22339835, 0.31820796, 0.50688522],
        [0.02794853, 0.03980962, 0.06341362]]),
 'tau_total': array([2.30618295, 3.28504631, 5.23328165]),
 'TR': array([[2.28910526, 1.86520154, 1.1888105 ],
        [2.28879859, 1.86491585, 1.18857141],
        [2.28841062, 1.86455441, 1.18826896],
        [2.2881045 , 1.86426923, 1.18803032],
        [2.28373743, 1.86020143, 1.1846276 ],
        [2.28369563, 1.8601625 , 1.18459504],
        [2.28356835, 1.86004396, 1.18449591],
        [2.28343176, 1.85991675, 1.18438954],
        [2.28326289, 1.85975948, 1.18425803]])}
[6]:
# Now we pack the simulated spectrum into a new SpecData instance
obs_1 = SpecData(
    freq_axis_1,
    sim_obs1,
    noise,
    xlabel=r"LSRK Frequency (MHz)",
    ylabel=r"$T_B$ (K)",
)
obs_2 = SpecData(
    freq_axis_2,
    sim_obs2,
    noise,
    xlabel=r"LSRK Frequency (MHz)",
    ylabel=r"$T_B$ (K)",
)
data = {"12CN-1": obs_1, "12CN-2": obs_2}

Model Definition

Finally, with our model definition and (simulated) data in hand, we can explore the capabilities of CNModel. Here we create a new model with the simulated data. We assume LTE.

[7]:
# Initialize and define the model
model = CNModel(
    data,
    molecule="CN", # molecule (either "CN" or "13CN")
    mol_data=mol_data_12CN, # molecular data
    bg_temp = 2.7, # assumed background temperature (K)
    Beff = 1.0, # beam efficiency
    Feff = 1.0, # forward efficiency
    n_clouds=n_clouds,
    baseline_degree=baseline_degree,
    seed=1234,
    verbose=True
)
model.add_priors(
    prior_log10_N = [13.5, 1.0], # mean and width of log10 total column density prior (cm-2)
    prior_log10_Tkin = [1.0, 0.5], # mean and width of log10 kinetic temperature prior (K)
    prior_velocity = [0.0, 5.0], # mean and width of velocity prior (km/s)
    prior_fwhm_nonthermal = 1.0, # width of non-thermal broadening prior (km/s)
    prior_fwhm_L = None, # assume Gaussian line profile
    prior_rms = None, # do not infer spectral rms
    prior_baseline_coeffs = None, # use default baseline priors
    assume_LTE = True, # assume kinetic temperature = excitation temperature
    prior_log10_Tex = None, # ignored for this LTE model
    assume_CTEX = True, # assume CTEX
    prior_log10_LTE_precision = None, # ignored for this LTE model
    fix_log10_Tkin = None, # do not fix the kinetic temperature
    clip_weights = 1.0e-9, # clip statistical weights between [clip_weights, 1-clip_weights]
    clip_tau = -10.0, # clip optical depths below to prevent masers
    ordered = False, # do not assume optically-thin
)
model.add_likelihood()
[8]:
# Plot model graph
model.graph().render('cn_model', format='png')
model.graph()
[8]:
../_images/notebooks_cn_model_12_0.svg
[9]:
# model string representation
print(model.model.str_repr())
baseline_12CN-1_norm ~ Normal(0, <constant>)
baseline_12CN-2_norm ~ Normal(0, <constant>)
       velocity_norm ~ Normal(0, 1)
     log10_Tkin_norm ~ Normal(0, 1)
fwhm_nonthermal_norm ~ HalfNormal(0, 1)
        log10_N_norm ~ Normal(0, 1)
            velocity ~ Deterministic(f(velocity_norm))
          log10_Tkin ~ Deterministic(f(log10_Tkin_norm))
        fwhm_thermal ~ Deterministic(f(log10_Tkin_norm))
     fwhm_nonthermal ~ Deterministic(f(fwhm_nonthermal_norm))
                fwhm ~ Deterministic(f(fwhm_nonthermal_norm, log10_Tkin_norm))
             log10_N ~ Deterministic(f(log10_N_norm))
        log10_Tex_ul ~ Deterministic(f(log10_Tkin_norm))
         LTE_weights ~ Deterministic(f(log10_Tkin_norm))
                 Tex ~ Deterministic(f(log10_Tkin_norm))
                 tau ~ Deterministic(f(log10_N_norm, log10_Tkin_norm))
           tau_total ~ Deterministic(f(log10_N_norm, log10_Tkin_norm))
                  TR ~ Deterministic(f(log10_Tkin_norm))
              12CN-1 ~ Normal(f(baseline_12CN-1_norm, log10_Tkin_norm, velocity_norm, log10_N_norm, fwhm_nonthermal_norm), <constant>)
              12CN-2 ~ Normal(f(baseline_12CN-2_norm, log10_Tkin_norm, velocity_norm, log10_N_norm, fwhm_nonthermal_norm), <constant>)

We check that our prior distributions are reasonable by drawing prior predictive checks. Each colored line is a simulated “observation” with parameters drawn from the prior distributions. You should check that these simulated observations at least somewhat overlap your actual observation (black line).

[10]:
from bayes_spec.plots import plot_predictive

# prior predictive check
prior = model.sample_prior_predictive(
    samples=1000,  # prior predictive samples
)
_ = plot_predictive(model.data, prior.prior_predictive)
Sampling: [12CN-1, 12CN-2, baseline_12CN-1_norm, baseline_12CN-2_norm, fwhm_nonthermal_norm, log10_N_norm, log10_Tkin_norm, velocity_norm]
../_images/notebooks_cn_model_15_1.png

We can also generate a pair plot to inspect the prior distributions and their effect on deterministic quantities. The model has several attributes to access the various free parameters (freeRVs) and deterministic quantities (deterministics). Here we show the pair plot for the deterministic quantities derived from our prior distributions. The three red points correspond to the simulation parameters (“truths”) for our three clouds.

[11]:
from bayes_spec.plots import plot_pair

# available parameter attributes:
print("baseline_freeRVs", model.baseline_freeRVs)
print("baseline_deterministics", model.baseline_deterministics)
print("cloud_freeRVs", model.cloud_freeRVs)
print("cloud_deterministics", model.cloud_deterministics)
print("hyper_freeRVs", model.hyper_freeRVs)
print("hyper_deterministics", model.hyper_deterministics)

# ignore transition and state dependent parameters
var_names = [
    param for param in model.cloud_deterministics
    if not set(model.model.named_vars_to_dims[param]).intersection(set(["transition", "state"]))
]
_ = plot_pair(
    prior.prior, # samples
    var_names, # var_names to plot
    labeller=model.labeller, # label manager
    kind="kde", # plot type
    reference_values=sim_params, # truths
)
baseline_freeRVs ['baseline_12CN-1_norm', 'baseline_12CN-2_norm']
baseline_deterministics []
cloud_freeRVs ['velocity_norm', 'log10_Tkin_norm', 'fwhm_nonthermal_norm', 'log10_N_norm']
cloud_deterministics ['velocity', 'log10_Tkin', 'fwhm_thermal', 'fwhm_nonthermal', 'fwhm', 'log10_N', 'log10_Tex_ul', 'LTE_weights', 'Tex', 'tau', 'tau_total', 'TR']
hyper_freeRVs []
hyper_deterministics []
../_images/notebooks_cn_model_17_1.png

Variational Inference

We can approximate the posterior distribution using variational inference.

[12]:
start = time.time()
model.fit(
    n = 100_000, # maximum number of VI iterations
    draws = 1_000, # number of posterior samples
    rel_tolerance = 0.05, # VI relative convergence threshold
    abs_tolerance = 0.05, # VI absolute convergence threshold
    learning_rate = 0.01, # VI learning rate
)
end = time.time()
print(f"Runtime: {(end-start)/60.0:.2f} minutes")
Convergence achieved at 8800
Interrupted at 8,799 [8%]: Average Loss = 1,173.3
Runtime: 0.29 minutes
[13]:
posterior = model.sample_posterior_predictive(
    thin=100, # keep one in {thin} posterior samples
)
_ = plot_predictive(model.data, posterior.posterior_predictive)
Sampling: [12CN-1, 12CN-2]
../_images/notebooks_cn_model_20_3.png

Posterior Sampling: MCMC

We can sample from the posterior distribution using MCMC.

[14]:
start = time.time()
init_kwargs = {
    "rel_tolerance": 0.05,
    "abs_tolerance": 0.05,
    "learning_rate": 0.01,
}
model.sample(
    init = "advi+adapt_diag", # initialization strategy
    tune = 1000, # tuning samples
    draws = 1000, # posterior samples
    chains = 8, # number of independent chains
    cores = 8, # number of parallel chains
    init_kwargs = init_kwargs, # VI initialization arguments
    nuts_kwargs = {"target_accept": 0.8}, # NUTS arguments
)
end = time.time()
print(f"Runtime: {(end-start)/60.0:.2f} minutes")
Initializing NUTS using custom advi+adapt_diag strategy
Convergence achieved at 8800
Interrupted at 8,799 [8%]: Average Loss = 1,173.3
Multiprocess sampling (8 chains in 8 jobs)
NUTS: [baseline_12CN-1_norm, baseline_12CN-2_norm, velocity_norm, log10_Tkin_norm, fwhm_nonthermal_norm, log10_N_norm]
Sampling 8 chains for 1_000 tune and 1_000 draw iterations (8_000 + 8_000 draws total) took 54 seconds.
Adding log-likelihood to trace
Runtime: 1.30 minutes
[15]:
model.solve(kl_div_threshold=0.1)
GMM converged to unique solution
[16]:
print("solutions:", model.solutions)

pm.summary(model.trace.solution_0)
solutions: [0]
[16]:
mean sd hdi_3% hdi_97% mcse_mean mcse_sd ess_bulk ess_tail r_hat
baseline_12CN-1_norm[0] -0.214 0.053 -0.316 -0.117 0.001 0.001 9051.0 6947.0 1.0
baseline_12CN-1_norm[1] -4.779 0.141 -5.034 -4.508 0.001 0.002 15012.0 6024.0 1.0
baseline_12CN-1_norm[2] 2.186 0.793 0.684 3.617 0.008 0.008 9344.0 6753.0 1.0
baseline_12CN-2_norm[0] -0.316 0.071 -0.447 -0.183 0.001 0.001 10084.0 6640.0 1.0
baseline_12CN-2_norm[1] -1.990 0.202 -2.362 -1.599 0.002 0.002 13096.0 6114.0 1.0
baseline_12CN-2_norm[2] 0.433 0.888 -1.242 2.045 0.008 0.010 11282.0 6694.0 1.0
velocity_norm[0] 0.004 0.003 -0.002 0.009 0.000 0.000 10185.0 6176.0 1.0
velocity_norm[1] -0.400 0.002 -0.404 -0.397 0.000 0.000 10409.0 6524.0 1.0
velocity_norm[2] 0.510 0.007 0.496 0.523 0.000 0.000 10767.0 6333.0 1.0
log10_Tkin_norm[0] -0.799 0.013 -0.823 -0.776 0.000 0.000 7311.0 6343.0 1.0
log10_Tkin_norm[1] -0.697 0.016 -0.725 -0.666 0.000 0.000 6276.0 5382.0 1.0
log10_Tkin_norm[2] -0.985 0.015 -1.012 -0.959 0.000 0.000 5838.0 5259.0 1.0
log10_N_norm[0] 0.409 0.026 0.362 0.459 0.000 0.000 7280.0 6375.0 1.0
log10_N_norm[1] 0.297 0.022 0.256 0.339 0.000 0.000 6354.0 5683.0 1.0
log10_N_norm[2] 0.425 0.064 0.303 0.543 0.001 0.001 6089.0 5224.0 1.0
fwhm_nonthermal_norm[0] 1.291 0.040 1.217 1.365 0.000 0.000 7479.0 6463.0 1.0
fwhm_nonthermal_norm[1] 1.007 0.026 0.959 1.055 0.000 0.000 8232.0 6164.0 1.0
fwhm_nonthermal_norm[2] 1.499 0.089 1.330 1.657 0.001 0.001 8609.0 6598.0 1.0
velocity[0] 0.019 0.015 -0.009 0.046 0.000 0.000 10185.0 6176.0 1.0
velocity[1] -2.002 0.010 -2.022 -1.983 0.000 0.000 10409.0 6524.0 1.0
velocity[2] 2.549 0.036 2.480 2.617 0.000 0.000 10767.0 6333.0 1.0
log10_Tkin[0] 0.601 0.006 0.588 0.612 0.000 0.000 7311.0 6343.0 1.0
log10_Tkin[1] 0.652 0.008 0.637 0.667 0.000 0.000 6276.0 5382.0 1.0
log10_Tkin[2] 0.507 0.007 0.494 0.521 0.000 0.000 5838.0 5259.0 1.0
fwhm_thermal[0] 0.084 0.001 0.083 0.085 0.000 0.000 7311.0 6343.0 1.0
fwhm_thermal[1] 0.089 0.001 0.087 0.090 0.000 0.000 6276.0 5382.0 1.0
fwhm_thermal[2] 0.075 0.001 0.074 0.076 0.000 0.000 5838.0 5259.0 1.0
fwhm_nonthermal[0] 1.291 0.040 1.217 1.365 0.000 0.000 7479.0 6463.0 1.0
fwhm_nonthermal[1] 1.007 0.026 0.959 1.055 0.000 0.000 8232.0 6164.0 1.0
fwhm_nonthermal[2] 1.499 0.089 1.330 1.657 0.001 0.001 8609.0 6598.0 1.0
fwhm[0] 1.294 0.040 1.220 1.368 0.000 0.000 7477.0 6463.0 1.0
fwhm[1] 1.011 0.026 0.963 1.058 0.000 0.000 8222.0 6189.0 1.0
fwhm[2] 1.501 0.089 1.332 1.659 0.001 0.001 8608.0 6598.0 1.0
log10_N[0] 13.909 0.026 13.862 13.959 0.000 0.000 7280.0 6375.0 1.0
log10_N[1] 13.797 0.022 13.756 13.839 0.000 0.000 6354.0 5683.0 1.0
log10_N[2] 13.925 0.064 13.803 14.043 0.001 0.001 6089.0 5224.0 1.0
log10_Tex_ul[0] 0.601 0.006 0.588 0.612 0.000 0.000 7311.0 6343.0 1.0
log10_Tex_ul[1] 0.652 0.008 0.637 0.667 0.000 0.000 6276.0 5382.0 1.0
log10_Tex_ul[2] 0.507 0.007 0.494 0.521 0.000 0.000 5838.0 5259.0 1.0
LTE_weights[0, 0 0 1 1] 0.189 0.002 0.186 0.192 0.000 0.000 7311.0 6343.0 1.0
LTE_weights[0, 0 0 1 2] 0.377 0.003 0.371 0.383 0.000 0.000 7311.0 6343.0 1.0
LTE_weights[0, 1 0 1 1] 0.048 0.001 0.047 0.049 0.000 0.000 7311.0 6343.0 1.0
LTE_weights[0, 1 0 1 2] 0.097 0.001 0.095 0.099 0.000 0.000 7311.0 6343.0 1.0
LTE_weights[0, 1 0 2 1] 0.048 0.001 0.047 0.049 0.000 0.000 7311.0 6343.0 1.0
LTE_weights[0, 1 0 2 2] 0.096 0.001 0.094 0.098 0.000 0.000 7311.0 6343.0 1.0
LTE_weights[0, 1 0 2 3] 0.144 0.002 0.141 0.148 0.000 0.000 7311.0 6343.0 1.0
LTE_weights[1, 0 0 1 1] 0.176 0.002 0.173 0.180 0.000 0.000 6276.0 5382.0 1.0
LTE_weights[1, 0 0 1 2] 0.353 0.004 0.346 0.359 0.000 0.000 6276.0 5382.0 1.0
LTE_weights[1, 1 0 1 1] 0.053 0.001 0.051 0.054 0.000 0.000 6276.0 5382.0 1.0
LTE_weights[1, 1 0 1 2] 0.105 0.001 0.103 0.107 0.000 0.000 6276.0 5382.0 1.0
LTE_weights[1, 1 0 2 1] 0.052 0.001 0.051 0.053 0.000 0.000 6276.0 5382.0 1.0
LTE_weights[1, 1 0 2 2] 0.105 0.001 0.102 0.107 0.000 0.000 6276.0 5382.0 1.0
LTE_weights[1, 1 0 2 3] 0.157 0.002 0.154 0.160 0.000 0.000 6276.0 5382.0 1.0
LTE_weights[2, 0 0 1 1] 0.215 0.002 0.210 0.218 0.000 0.000 5838.0 5259.0 1.0
LTE_weights[2, 0 0 1 2] 0.429 0.004 0.421 0.437 0.000 0.000 5838.0 5259.0 1.0
LTE_weights[2, 1 0 1 1] 0.040 0.001 0.038 0.041 0.000 0.000 5838.0 5259.0 1.0
LTE_weights[2, 1 0 1 2] 0.079 0.001 0.077 0.082 0.000 0.000 5838.0 5259.0 1.0
LTE_weights[2, 1 0 2 1] 0.039 0.001 0.038 0.041 0.000 0.000 5838.0 5259.0 1.0
LTE_weights[2, 1 0 2 2] 0.079 0.001 0.076 0.082 0.000 0.000 5838.0 5259.0 1.0
LTE_weights[2, 1 0 2 3] 0.118 0.002 0.115 0.123 0.000 0.000 5838.0 5259.0 1.0
Tex[113123.3687, 0] 3.988 0.059 3.876 4.093 0.001 0.001 7311.0 6343.0 1.0
Tex[113123.3687, 1] 4.485 0.081 4.339 4.644 0.001 0.001 6276.0 5382.0 1.0
Tex[113123.3687, 2] 3.217 0.054 3.119 3.316 0.001 0.001 5838.0 5259.0 1.0
Tex[113144.19, 0] 3.988 0.059 3.876 4.093 0.001 0.001 7311.0 6343.0 1.0
Tex[113144.19, 1] 4.485 0.081 4.339 4.644 0.001 0.001 6276.0 5382.0 1.0
Tex[113144.19, 2] 3.217 0.054 3.119 3.316 0.001 0.001 5838.0 5259.0 1.0
Tex[113170.535, 0] 3.988 0.059 3.876 4.093 0.001 0.001 7311.0 6343.0 1.0
Tex[113170.535, 1] 4.485 0.081 4.339 4.644 0.001 0.001 6276.0 5382.0 1.0
Tex[113170.535, 2] 3.217 0.054 3.119 3.316 0.001 0.001 5838.0 5259.0 1.0
Tex[113191.325, 0] 3.988 0.059 3.876 4.093 0.001 0.001 7311.0 6343.0 1.0
Tex[113191.325, 1] 4.485 0.081 4.339 4.644 0.001 0.001 6276.0 5382.0 1.0
Tex[113191.325, 2] 3.217 0.054 3.119 3.316 0.001 0.001 5838.0 5259.0 1.0
Tex[113488.142, 0] 3.988 0.059 3.876 4.093 0.001 0.001 7311.0 6343.0 1.0
Tex[113488.142, 1] 4.485 0.081 4.339 4.644 0.001 0.001 6276.0 5382.0 1.0
Tex[113488.142, 2] 3.217 0.054 3.119 3.316 0.001 0.001 5838.0 5259.0 1.0
Tex[113490.985, 0] 3.988 0.059 3.876 4.093 0.001 0.001 7311.0 6343.0 1.0
Tex[113490.985, 1] 4.485 0.081 4.339 4.644 0.001 0.001 6276.0 5382.0 1.0
Tex[113490.985, 2] 3.217 0.054 3.119 3.316 0.001 0.001 5838.0 5259.0 1.0
Tex[113499.643, 0] 3.988 0.059 3.876 4.093 0.001 0.001 7311.0 6343.0 1.0
Tex[113499.643, 1] 4.485 0.081 4.339 4.644 0.001 0.001 6276.0 5382.0 1.0
Tex[113499.643, 2] 3.217 0.054 3.119 3.316 0.001 0.001 5838.0 5259.0 1.0
Tex[113508.934, 0] 3.988 0.059 3.876 4.093 0.001 0.001 7311.0 6343.0 1.0
Tex[113508.934, 1] 4.485 0.081 4.339 4.644 0.001 0.001 6276.0 5382.0 1.0
Tex[113508.934, 2] 3.217 0.054 3.119 3.316 0.001 0.001 5838.0 5259.0 1.0
Tex[113520.4215, 0] 3.988 0.059 3.876 4.093 0.001 0.001 7311.0 6343.0 1.0
Tex[113520.4215, 1] 4.485 0.081 4.339 4.644 0.001 0.001 6276.0 5382.0 1.0
Tex[113520.4215, 2] 3.217 0.054 3.119 3.316 0.001 0.001 5838.0 5259.0 1.0
tau[113123.3687, 0] 0.040 0.003 0.035 0.046 0.000 0.000 7276.0 6320.0 1.0
tau[113123.3687, 1] 0.028 0.002 0.024 0.031 0.000 0.000 6278.0 5414.0 1.0
tau[113123.3687, 2] 0.053 0.009 0.037 0.069 0.000 0.000 6055.0 5206.0 1.0
tau[113144.19, 0] 0.331 0.025 0.287 0.379 0.000 0.000 7276.0 6320.0 1.0
tau[113144.19, 1] 0.226 0.016 0.196 0.255 0.000 0.000 6278.0 5414.0 1.0
tau[113144.19, 2] 0.433 0.070 0.305 0.567 0.001 0.001 6055.0 5206.0 1.0
tau[113170.535, 0] 0.323 0.024 0.280 0.370 0.000 0.000 7276.0 6320.0 1.0
tau[113170.535, 1] 0.220 0.015 0.192 0.249 0.000 0.000 6278.0 5414.0 1.0
tau[113170.535, 2] 0.423 0.069 0.298 0.554 0.001 0.001 6055.0 5206.0 1.0
tau[113191.325, 0] 0.420 0.031 0.364 0.481 0.000 0.000 7276.0 6320.0 1.0
tau[113191.325, 1] 0.286 0.020 0.249 0.323 0.000 0.000 6278.0 5414.0 1.0
tau[113191.325, 2] 0.549 0.089 0.387 0.719 0.001 0.001 6055.0 5206.0 1.0
tau[113488.142, 0] 0.422 0.031 0.366 0.482 0.000 0.000 7276.0 6320.0 1.0
tau[113488.142, 1] 0.287 0.020 0.250 0.324 0.000 0.000 6278.0 5414.0 1.0
tau[113488.142, 2] 0.551 0.089 0.388 0.722 0.001 0.001 6055.0 5206.0 1.0
tau[113490.985, 0] 1.120 0.083 0.971 1.282 0.001 0.001 7276.0 6320.0 1.0
tau[113490.985, 1] 0.763 0.053 0.664 0.862 0.001 0.001 6278.0 5414.0 1.0
tau[113490.985, 2] 1.464 0.238 1.031 1.918 0.003 0.003 6055.0 5206.0 1.0
tau[113499.643, 0] 0.333 0.025 0.288 0.381 0.000 0.000 7276.0 6320.0 1.0
tau[113499.643, 1] 0.227 0.016 0.197 0.256 0.000 0.000 6278.0 5414.0 1.0
tau[113499.643, 2] 0.435 0.071 0.306 0.570 0.001 0.001 6055.0 5206.0 1.0
tau[113508.934, 0] 0.325 0.024 0.282 0.372 0.000 0.000 7276.0 6320.0 1.0
tau[113508.934, 1] 0.221 0.015 0.193 0.250 0.000 0.000 6278.0 5414.0 1.0
tau[113508.934, 2] 0.425 0.069 0.299 0.556 0.001 0.001 6055.0 5206.0 1.0
tau[113520.4215, 0] 0.041 0.003 0.035 0.047 0.000 0.000 7276.0 6320.0 1.0
tau[113520.4215, 1] 0.028 0.002 0.024 0.031 0.000 0.000 6278.0 5414.0 1.0
tau[113520.4215, 2] 0.053 0.009 0.037 0.070 0.000 0.000 6055.0 5206.0 1.0
tau_total[0] 3.355 0.248 2.909 3.840 0.003 0.003 7276.0 6320.0 1.0
tau_total[1] 2.285 0.159 1.988 2.581 0.002 0.002 6278.0 5414.0 1.0
tau_total[2] 4.387 0.712 3.090 5.745 0.009 0.008 6055.0 5206.0 1.0
TR[113123.3687, 0] 1.871 0.051 1.775 1.962 0.001 0.001 7311.0 6343.0 1.0
TR[113123.3687, 1] 2.306 0.072 2.170 2.440 0.001 0.001 6276.0 5382.0 1.0
TR[113123.3687, 2] 1.233 0.043 1.155 1.311 0.001 0.001 5838.0 5259.0 1.0
TR[113144.19, 0] 1.871 0.051 1.775 1.962 0.001 0.001 7311.0 6343.0 1.0
TR[113144.19, 1] 2.305 0.072 2.170 2.440 0.001 0.001 6276.0 5382.0 1.0
TR[113144.19, 2] 1.232 0.043 1.154 1.311 0.001 0.001 5838.0 5259.0 1.0
TR[113170.535, 0] 1.871 0.051 1.775 1.961 0.001 0.001 7311.0 6343.0 1.0
TR[113170.535, 1] 2.305 0.072 2.170 2.439 0.001 0.001 6276.0 5382.0 1.0
TR[113170.535, 2] 1.232 0.043 1.154 1.310 0.001 0.001 5838.0 5259.0 1.0
TR[113191.325, 0] 1.870 0.051 1.774 1.961 0.001 0.001 7311.0 6343.0 1.0
TR[113191.325, 1] 2.305 0.072 2.169 2.439 0.001 0.001 6276.0 5382.0 1.0
TR[113191.325, 2] 1.232 0.043 1.154 1.310 0.001 0.001 5838.0 5259.0 1.0
TR[113488.142, 0] 1.866 0.051 1.770 1.957 0.001 0.001 7311.0 6343.0 1.0
TR[113488.142, 1] 2.300 0.072 2.165 2.435 0.001 0.001 6276.0 5382.0 1.0
TR[113488.142, 2] 1.228 0.043 1.150 1.307 0.001 0.001 5838.0 5259.0 1.0
TR[113490.985, 0] 1.866 0.051 1.770 1.957 0.001 0.001 7311.0 6343.0 1.0
TR[113490.985, 1] 2.300 0.072 2.165 2.434 0.001 0.001 6276.0 5382.0 1.0
TR[113490.985, 2] 1.228 0.043 1.150 1.307 0.001 0.001 5838.0 5259.0 1.0
TR[113499.643, 0] 1.866 0.051 1.770 1.957 0.001 0.001 7311.0 6343.0 1.0
TR[113499.643, 1] 2.300 0.072 2.165 2.434 0.001 0.001 6276.0 5382.0 1.0
TR[113499.643, 2] 1.228 0.043 1.150 1.306 0.001 0.001 5838.0 5259.0 1.0
TR[113508.934, 0] 1.866 0.051 1.770 1.957 0.001 0.001 7311.0 6343.0 1.0
TR[113508.934, 1] 2.300 0.072 2.165 2.434 0.001 0.001 6276.0 5382.0 1.0
TR[113508.934, 2] 1.228 0.043 1.150 1.306 0.001 0.001 5838.0 5259.0 1.0
TR[113520.4215, 0] 1.866 0.051 1.770 1.956 0.001 0.001 7311.0 6343.0 1.0
TR[113520.4215, 1] 2.300 0.072 2.165 2.434 0.001 0.001 6276.0 5382.0 1.0
TR[113520.4215, 2] 1.228 0.043 1.150 1.306 0.001 0.001 5838.0 5259.0 1.0

We generate posterior predictive checks as well as a trace plot of the individual chains. In the posterior predictive plot, we show each chain as a different color. Each line is one posterior sample.

[17]:
posterior = model.sample_posterior_predictive(
    thin=10, # keep one in {thin} posterior samples
)
_ = plot_predictive(model.data, posterior.posterior_predictive)
Sampling: [12CN-1, 12CN-2]
../_images/notebooks_cn_model_26_3.png
[18]:
from bayes_spec.plots import plot_traces

axes = plot_traces(model.trace.solution_0, model.cloud_freeRVs + model.baseline_freeRVs + model.hyper_freeRVs)
fig = axes.ravel()[0].figure
fig.tight_layout()
../_images/notebooks_cn_model_27_0.png

We can inspect the posterior distribution pair plots. The red points represent the simulation parameters.

[19]:
from bayes_spec.plots import plot_pair

# ignore transition and state dependent parameters
var_names = [
    param for param in model.cloud_deterministics
    if not set(model.model.named_vars_to_dims[param]).intersection(set(["transition", "state"]))
]
_ = plot_pair(
    model.trace.solution_0, # samples
    var_names, # var_names to plot
    labeller=model.labeller, # label manager
    kind="kde", # plot type
    reference_values=sim_params, # truths
)
../_images/notebooks_cn_model_29_0.png

Notice that there are three posterior modes. These correspond to the three clouds of the model. We can plot the posterior distributions of the deterministic quantities for a single cloud (excluding the transition and state dependent parameters for clarity) along with the model hyper-parameters.

[20]:
# identify simulation cloud corresponding to each posterior cloud
sim_cloud_map = {}
for i in range(n_clouds):
    posterior_velocity = model.trace.solution_0['velocity'].sel(cloud=i).data.mean()
    match = np.argmin(np.abs(sim_params["velocity"] - posterior_velocity))
    sim_cloud_map[i] = match
sim_cloud_map
[20]:
{0: np.int64(1), 1: np.int64(0), 2: np.int64(2)}
[21]:
cloud = 0

# subset of sim_params
my_sim_params = {}
for var_name in model.cloud_deterministics:
    my_sim_params[var_name] = sim_params[var_name][sim_cloud_map[cloud]]

# ignore transition and state dependent parameters
var_names = [
    param for param in model.cloud_deterministics
    if not set(model.model.named_vars_to_dims[param]).intersection(set(["transition", "state"]))
]
_ = plot_pair(
    model.trace.solution_0.sel(cloud=cloud), # samples
    var_names, # var_names to plot
    labeller=model.labeller, # label manager
    kind="kde", # plot type
    reference_values=my_sim_params, # truths
)
../_images/notebooks_cn_model_32_0.png
[22]:
cloud = 1

# subset of sim_params
my_sim_params = {}
for var_name in model.cloud_deterministics:
    my_sim_params[var_name] = sim_params[var_name][sim_cloud_map[cloud]]

# ignore transition and state dependent parameters
var_names = [
    param for param in model.cloud_deterministics
    if not set(model.model.named_vars_to_dims[param]).intersection(set(["transition", "state"]))
]
_ = plot_pair(
    model.trace.solution_0.sel(cloud=cloud), # samples
    var_names, # var_names to plot
    labeller=model.labeller, # label manager
    kind="kde", # plot type
    reference_values=my_sim_params, # truths
)
../_images/notebooks_cn_model_33_0.png
[23]:
cloud = 2

# subset of sim_params
my_sim_params = {}
for var_name in model.cloud_deterministics:
    my_sim_params[var_name] = sim_params[var_name][sim_cloud_map[cloud]]

# ignore transition and state dependent parameters
var_names = [
    param for param in model.cloud_deterministics
    if not set(model.model.named_vars_to_dims[param]).intersection(set(["transition", "state"]))
]
_ = plot_pair(
    model.trace.solution_0.sel(cloud=cloud), # samples
    var_names, # var_names to plot
    labeller=model.labeller, # label manager
    kind="kde", # plot type
    reference_values=my_sim_params, # truths
)
../_images/notebooks_cn_model_34_0.png

Finally, we can get the posterior statistics, Bayesian Information Criterion (BIC), etc.

[24]:
var_names=model.cloud_deterministics + model.baseline_freeRVs + model.hyper_deterministics
point_stats = az.summary(model.trace.solution_0, var_names=var_names, kind='stats', hdi_prob=0.68)
print("BIC:", model.bic())
display(point_stats)
BIC: -3441.9452824798577
mean sd hdi_16% hdi_84%
velocity[0] 0.019 0.015 0.005 0.035
velocity[1] -2.002 0.010 -2.013 -1.993
velocity[2] 2.549 0.036 2.513 2.584
log10_Tkin[0] 0.601 0.006 0.594 0.606
log10_Tkin[1] 0.652 0.008 0.644 0.659
log10_Tkin[2] 0.507 0.007 0.500 0.513
fwhm_thermal[0] 0.084 0.001 0.083 0.084
fwhm_thermal[1] 0.089 0.001 0.088 0.090
fwhm_thermal[2] 0.075 0.001 0.075 0.076
fwhm_nonthermal[0] 1.291 0.040 1.252 1.330
fwhm_nonthermal[1] 1.007 0.026 0.981 1.032
fwhm_nonthermal[2] 1.499 0.089 1.406 1.579
fwhm[0] 1.294 0.040 1.254 1.332
fwhm[1] 1.011 0.026 0.986 1.037
fwhm[2] 1.501 0.089 1.408 1.580
log10_N[0] 13.909 0.026 13.881 13.933
log10_N[1] 13.797 0.022 13.774 13.818
log10_N[2] 13.925 0.064 13.868 13.995
log10_Tex_ul[0] 0.601 0.006 0.594 0.606
log10_Tex_ul[1] 0.652 0.008 0.644 0.659
log10_Tex_ul[2] 0.507 0.007 0.500 0.513
LTE_weights[0, 0 0 1 1] 0.189 0.002 0.187 0.191
LTE_weights[0, 0 0 1 2] 0.377 0.003 0.375 0.381
LTE_weights[0, 1 0 1 1] 0.048 0.001 0.048 0.049
LTE_weights[0, 1 0 1 2] 0.097 0.001 0.095 0.098
LTE_weights[0, 1 0 2 1] 0.048 0.001 0.048 0.049
LTE_weights[0, 1 0 2 2] 0.096 0.001 0.095 0.097
LTE_weights[0, 1 0 2 3] 0.144 0.002 0.143 0.146
LTE_weights[1, 0 0 1 1] 0.176 0.002 0.175 0.178
LTE_weights[1, 0 0 1 2] 0.353 0.004 0.349 0.356
LTE_weights[1, 1 0 1 1] 0.053 0.001 0.052 0.053
LTE_weights[1, 1 0 1 2] 0.105 0.001 0.104 0.106
LTE_weights[1, 1 0 2 1] 0.052 0.001 0.052 0.053
LTE_weights[1, 1 0 2 2] 0.105 0.001 0.103 0.106
LTE_weights[1, 1 0 2 3] 0.157 0.002 0.155 0.159
LTE_weights[2, 0 0 1 1] 0.215 0.002 0.213 0.217
LTE_weights[2, 0 0 1 2] 0.429 0.004 0.426 0.434
LTE_weights[2, 1 0 1 1] 0.040 0.001 0.039 0.040
LTE_weights[2, 1 0 1 2] 0.079 0.001 0.078 0.081
LTE_weights[2, 1 0 2 1] 0.039 0.001 0.039 0.040
LTE_weights[2, 1 0 2 2] 0.079 0.001 0.077 0.080
LTE_weights[2, 1 0 2 3] 0.118 0.002 0.116 0.120
Tex[113123.3687, 0] 3.988 0.059 3.921 4.038
Tex[113123.3687, 1] 4.485 0.081 4.401 4.561
Tex[113123.3687, 2] 3.217 0.054 3.159 3.261
Tex[113144.19, 0] 3.988 0.059 3.921 4.038
Tex[113144.19, 1] 4.485 0.081 4.401 4.561
Tex[113144.19, 2] 3.217 0.054 3.159 3.261
Tex[113170.535, 0] 3.988 0.059 3.921 4.038
Tex[113170.535, 1] 4.485 0.081 4.401 4.561
Tex[113170.535, 2] 3.217 0.054 3.159 3.261
Tex[113191.325, 0] 3.988 0.059 3.921 4.038
Tex[113191.325, 1] 4.485 0.081 4.401 4.561
Tex[113191.325, 2] 3.217 0.054 3.159 3.261
Tex[113488.142, 0] 3.988 0.059 3.921 4.038
Tex[113488.142, 1] 4.485 0.081 4.401 4.561
Tex[113488.142, 2] 3.217 0.054 3.159 3.261
Tex[113490.985, 0] 3.988 0.059 3.921 4.038
Tex[113490.985, 1] 4.485 0.081 4.401 4.561
Tex[113490.985, 2] 3.217 0.054 3.159 3.261
Tex[113499.643, 0] 3.988 0.059 3.921 4.038
Tex[113499.643, 1] 4.485 0.081 4.401 4.561
Tex[113499.643, 2] 3.217 0.054 3.159 3.261
Tex[113508.934, 0] 3.988 0.059 3.921 4.038
Tex[113508.934, 1] 4.485 0.081 4.401 4.561
Tex[113508.934, 2] 3.217 0.054 3.159 3.261
Tex[113520.4215, 0] 3.988 0.059 3.921 4.038
Tex[113520.4215, 1] 4.485 0.081 4.401 4.561
Tex[113520.4215, 2] 3.217 0.054 3.159 3.261
tau[113123.3687, 0] 0.040 0.003 0.037 0.043
tau[113123.3687, 1] 0.028 0.002 0.026 0.029
tau[113123.3687, 2] 0.053 0.009 0.043 0.060
tau[113144.19, 0] 0.331 0.025 0.304 0.353
tau[113144.19, 1] 0.226 0.016 0.210 0.241
tau[113144.19, 2] 0.433 0.070 0.354 0.491
tau[113170.535, 0] 0.323 0.024 0.297 0.345
tau[113170.535, 1] 0.220 0.015 0.205 0.235
tau[113170.535, 2] 0.423 0.069 0.346 0.480
tau[113191.325, 0] 0.420 0.031 0.386 0.448
tau[113191.325, 1] 0.286 0.020 0.266 0.306
tau[113191.325, 2] 0.549 0.089 0.449 0.623
tau[113488.142, 0] 0.422 0.031 0.387 0.449
tau[113488.142, 1] 0.287 0.020 0.267 0.307
tau[113488.142, 2] 0.551 0.089 0.451 0.626
tau[113490.985, 0] 1.120 0.083 1.029 1.194
tau[113490.985, 1] 0.763 0.053 0.711 0.815
tau[113490.985, 2] 1.464 0.238 1.198 1.663
tau[113499.643, 0] 0.333 0.025 0.306 0.355
tau[113499.643, 1] 0.227 0.016 0.211 0.242
tau[113499.643, 2] 0.435 0.071 0.356 0.494
tau[113508.934, 0] 0.325 0.024 0.299 0.346
tau[113508.934, 1] 0.221 0.015 0.206 0.237
tau[113508.934, 2] 0.425 0.069 0.348 0.482
tau[113520.4215, 0] 0.041 0.003 0.037 0.043
tau[113520.4215, 1] 0.028 0.002 0.026 0.030
tau[113520.4215, 2] 0.053 0.009 0.043 0.060
tau_total[0] 3.355 0.248 3.082 3.576
tau_total[1] 2.285 0.159 2.128 2.443
tau_total[2] 4.387 0.712 3.585 4.977
TR[113123.3687, 0] 1.871 0.051 1.814 1.914
TR[113123.3687, 1] 2.306 0.072 2.231 2.373
TR[113123.3687, 2] 1.233 0.043 1.183 1.264
TR[113144.19, 0] 1.871 0.051 1.814 1.914
TR[113144.19, 1] 2.305 0.072 2.231 2.372
TR[113144.19, 2] 1.232 0.043 1.183 1.264
TR[113170.535, 0] 1.871 0.051 1.813 1.913
TR[113170.535, 1] 2.305 0.072 2.231 2.372
TR[113170.535, 2] 1.232 0.043 1.183 1.264
TR[113191.325, 0] 1.870 0.051 1.813 1.913
TR[113191.325, 1] 2.305 0.072 2.230 2.372
TR[113191.325, 2] 1.232 0.043 1.183 1.263
TR[113488.142, 0] 1.866 0.051 1.809 1.909
TR[113488.142, 1] 2.300 0.072 2.226 2.367
TR[113488.142, 2] 1.228 0.043 1.179 1.260
TR[113490.985, 0] 1.866 0.051 1.809 1.909
TR[113490.985, 1] 2.300 0.072 2.226 2.367
TR[113490.985, 2] 1.228 0.043 1.179 1.260
TR[113499.643, 0] 1.866 0.051 1.809 1.909
TR[113499.643, 1] 2.300 0.072 2.226 2.367
TR[113499.643, 2] 1.228 0.043 1.179 1.260
TR[113508.934, 0] 1.866 0.051 1.809 1.908
TR[113508.934, 1] 2.300 0.072 2.226 2.367
TR[113508.934, 2] 1.228 0.043 1.179 1.260
TR[113520.4215, 0] 1.866 0.051 1.809 1.908
TR[113520.4215, 1] 2.300 0.072 2.225 2.367
TR[113520.4215, 2] 1.228 0.043 1.179 1.260
baseline_12CN-1_norm[0] -0.214 0.053 -0.266 -0.160
baseline_12CN-1_norm[1] -4.779 0.141 -4.913 -4.628
baseline_12CN-1_norm[2] 2.186 0.793 1.398 2.983
baseline_12CN-2_norm[0] -0.316 0.071 -0.387 -0.248
baseline_12CN-2_norm[1] -1.990 0.202 -2.187 -1.788
baseline_12CN-2_norm[2] 0.433 0.888 -0.358 1.435
[ ]: