Mixture Extension#

We use the same dataset from Getting Started with a mixture model.

import os

import pandas as pd
import hbmep as mep

url = "https://raw.githubusercontent.com/hbmep/hbmep/refs/heads/docs-data/data/mock_data.csv"
df = pd.read_csv(url)

Build the model#

model = mep.StandardHB()

# Point to the respective columns in dataframe
model.intensity = "TMSIntensity"
model.features = ["participant"]
model.response = ["PKPK_ECR", "PKPK_FCR"]

# Set the function
model._model = model.rectified_logistic

# Enable mixture
model.use_mixture = True

Running the model#

# Process the dataframe
df, encoder = model.process(df)

# Run
mcmc, posterior = model.run(df=df)

# Check convergence diagnostics
summary_df = model.summary(posterior)
print(summary_df.to_string())
Hide code cell output
2026-09-21 14:42:57,499 - hbmep.util.util - INFO - func:process took: 0.01 sec
2026-09-21 14:42:59,024 - hbmep.util.util - INFO - func:trace took: 1.53 sec
2026-09-21 14:42:59,025 - hbmep.model.base_model - INFO - Running...
  0%|                                          | 0/3000 [00:00<?, ?it/s]
Compiling.. :   0%|                            | 0/3000 [00:00<?, ?it/s]

  0%|                                          | 0/3000 [00:00<?, ?it/s]


Compiling.. :   0%|                            | 0/3000 [00:00<?, ?it/s]


  0%|                                          | 0/3000 [00:00<?, ?it/s]


Compiling.. :   0%|                            | 0/3000 [00:00<?, ?it/s]


  0%|                                          | 0/3000 [00:00<?, ?it/s]


Compiling.. :   0%|                            | 0/3000 [00:00<?, ?it/s]

Running chain 0:   0%|                         | 0/3000 [00:02<?, ?it/s]

Running chain 1:   0%|                         | 0/3000 [00:02<?, ?it/s]


Running chain 2:   0%|                         | 0/3000 [00:02<?, ?it/s]


Running chain 3:   0%|                         | 0/3000 [00:02<?, ?it/s]


Running chain 2:   5%|▊              | 150/3000 [00:07<01:31, 31.17it/s]

Running chain 0:   5%|▊              | 150/3000 [00:07<01:33, 30.52it/s]

Running chain 1:   5%|▊              | 150/3000 [00:07<01:35, 29.90it/s]


Running chain 3:   5%|▊              | 150/3000 [00:07<01:35, 29.82it/s]


Running chain 2:  10%|█▌             | 300/3000 [00:08<00:49, 54.65it/s]

Running chain 0:  10%|█▌             | 300/3000 [00:08<00:50, 53.40it/s]

Running chain 1:  10%|█▌             | 300/3000 [00:08<00:51, 52.42it/s]


Running chain 3:  10%|█▌             | 300/3000 [00:08<00:52, 51.60it/s]

Running chain 0:  15%|██▎            | 450/3000 [00:09<00:32, 79.06it/s]

Running chain 2:  15%|██▎            | 450/3000 [00:09<00:33, 76.57it/s]


Running chain 1:  15%|██▎            | 450/3000 [00:09<00:33, 75.87it/s]


Running chain 3:  15%|██▎            | 450/3000 [00:09<00:33, 75.65it/s]

Running chain 0:  20%|███            | 600/3000 [00:10<00:24, 97.61it/s]

Running chain 2:  20%|███            | 600/3000 [00:10<00:26, 91.48it/s]


Running chain 1:  20%|███            | 600/3000 [00:10<00:26, 90.77it/s]


Running chain 3:  20%|███            | 600/3000 [00:10<00:27, 88.57it/s]

Running chain 0:  25%|███▌          | 750/3000 [00:11<00:19, 117.37it/s]

Running chain 2:  25%|███▌          | 750/3000 [00:11<00:20, 109.98it/s]


Running chain 1:  25%|███▌          | 750/3000 [00:11<00:19, 113.29it/s]


Running chain 3:  25%|███▌          | 750/3000 [00:11<00:21, 104.43it/s]

Running chain 0:  30%|████▏         | 900/3000 [00:12<00:16, 129.86it/s]

Running chain 1:  30%|████▏         | 900/3000 [00:12<00:16, 125.96it/s]


Running chain 2:  30%|████▏         | 900/3000 [00:12<00:17, 116.86it/s]


Running chain 3:  30%|████▏         | 900/3000 [00:12<00:17, 119.35it/s]

Running chain 0:  35%|████▌        | 1050/3000 [00:13<00:13, 141.08it/s]

Running chain 1:  35%|████▌        | 1050/3000 [00:13<00:14, 138.75it/s]


Running chain 2:  35%|████▌        | 1050/3000 [00:13<00:15, 128.33it/s]


Running chain 3:  35%|████▌        | 1050/3000 [00:13<00:14, 134.67it/s]

Running chain 0:  40%|█████▏       | 1200/3000 [00:13<00:11, 153.29it/s]

Running chain 1:  40%|█████▏       | 1200/3000 [00:14<00:11, 154.06it/s]


Running chain 2:  40%|█████▏       | 1200/3000 [00:14<00:12, 142.01it/s]


Running chain 3:  40%|█████▏       | 1200/3000 [00:14<00:12, 145.08it/s]

Running chain 0:  45%|█████▊       | 1350/3000 [00:14<00:10, 163.24it/s]

Running chain 1:  45%|█████▊       | 1350/3000 [00:14<00:10, 163.41it/s]


Running chain 2:  45%|█████▊       | 1350/3000 [00:15<00:10, 153.70it/s]


Running chain 3:  45%|█████▊       | 1350/3000 [00:15<00:10, 155.16it/s]

Running chain 0:  50%|██████▌      | 1500/3000 [00:15<00:08, 171.97it/s]

Running chain 1:  50%|██████▌      | 1500/3000 [00:15<00:08, 169.95it/s]


Running chain 2:  50%|██████▌      | 1500/3000 [00:16<00:09, 158.94it/s]

Running chain 0:  55%|███████▏     | 1650/3000 [00:16<00:07, 177.32it/s]

Running chain 3:  50%|██████▌      | 1500/3000 [00:16<00:09, 162.38it/s]


Running chain 1:  55%|███████▏     | 1650/3000 [00:16<00:07, 181.30it/s]


Running chain 2:  55%|███████▏     | 1650/3000 [00:16<00:08, 166.25it/s]


Running chain 3:  55%|███████▏     | 1650/3000 [00:16<00:08, 168.06it/s]

Running chain 0:  60%|███████▊     | 1800/3000 [00:17<00:06, 176.64it/s]

Running chain 1:  60%|███████▊     | 1800/3000 [00:17<00:06, 187.36it/s]


Running chain 2:  60%|███████▊     | 1800/3000 [00:17<00:06, 172.19it/s]


Running chain 3:  60%|███████▊     | 1800/3000 [00:17<00:06, 177.81it/s]

Running chain 0:  65%|████████▍    | 1950/3000 [00:17<00:05, 182.71it/s]

Running chain 1:  65%|████████▍    | 1950/3000 [00:17<00:05, 196.75it/s]


Running chain 3:  65%|████████▍    | 1950/3000 [00:18<00:05, 189.73it/s]


Running chain 2:  65%|████████▍    | 1950/3000 [00:18<00:05, 175.78it/s]

Running chain 0:  70%|█████████    | 2100/3000 [00:18<00:05, 172.73it/s]

Running chain 1:  70%|█████████    | 2100/3000 [00:18<00:05, 175.61it/s]

Running chain 0:  75%|█████████▊   | 2250/3000 [00:19<00:04, 163.77it/s]

Running chain 3:  70%|█████████    | 2100/3000 [00:19<00:05, 153.47it/s]


Running chain 2:  70%|█████████    | 2100/3000 [00:19<00:05, 151.46it/s]


Running chain 1:  75%|█████████▊   | 2250/3000 [00:19<00:04, 160.73it/s]

Running chain 0:  80%|██████████▍  | 2400/3000 [00:20<00:03, 159.29it/s]

Running chain 2:  75%|█████████▊   | 2250/3000 [00:20<00:05, 148.30it/s]


Running chain 1:  80%|██████████▍  | 2400/3000 [00:20<00:03, 158.22it/s]


Running chain 3:  75%|█████████▊   | 2250/3000 [00:21<00:05, 142.80it/s]

Running chain 0:  85%|███████████  | 2550/3000 [00:21<00:02, 161.40it/s]

Running chain 2:  80%|██████████▍  | 2400/3000 [00:21<00:04, 147.33it/s]


Running chain 1:  85%|███████████  | 2550/3000 [00:21<00:02, 156.67it/s]


Running chain 3:  80%|██████████▍  | 2400/3000 [00:22<00:04, 136.37it/s]

Running chain 0:  90%|███████████▋ | 2700/3000 [00:22<00:01, 160.89it/s]

Running chain 1:  90%|███████████▋ | 2700/3000 [00:22<00:01, 160.37it/s]


Running chain 2:  85%|███████████  | 2550/3000 [00:22<00:03, 148.36it/s]


Running chain 3:  85%|███████████  | 2550/3000 [00:23<00:03, 138.87it/s]

Running chain 0:  95%|████████████▎| 2850/3000 [00:23<00:00, 163.66it/s]

Running chain 1:  95%|████████████▎| 2850/3000 [00:23<00:00, 157.78it/s]


Running chain 2:  90%|███████████▋ | 2700/3000 [00:23<00:01, 150.78it/s]


Running chain 3:  90%|███████████▋ | 2700/3000 [00:24<00:02, 140.10it/s]

Running chain 0: 100%|█████████████| 3000/3000 [00:24<00:00, 161.04it/s]
Running chain 0: 100%|█████████████| 3000/3000 [00:24<00:00, 122.65it/s]


Running chain 2:  95%|████████████▎| 2850/3000 [00:24<00:00, 155.03it/s]


Running chain 1: 100%|█████████████| 3000/3000 [00:24<00:00, 156.28it/s]

Running chain 1: 100%|█████████████| 3000/3000 [00:24<00:00, 120.99it/s]


Running chain 3:  95%|████████████▎| 2850/3000 [00:25<00:01, 140.75it/s]


Running chain 2: 100%|█████████████| 3000/3000 [00:25<00:00, 156.08it/s]

Running chain 2: 100%|█████████████| 3000/3000 [00:25<00:00, 116.78it/s]


Running chain 3: 100%|█████████████| 3000/3000 [00:26<00:00, 143.34it/s]

Running chain 3: 100%|█████████████| 3000/3000 [00:26<00:00, 113.78it/s]
2026-09-21 14:43:25,822 - hbmep.util.util - INFO - func:run took: 28.32 sec
2026-09-21 14:43:25,953 - hbmep.util.util - INFO - func:summary took: 0.13 sec
                mean     sd  hdi_2.5%  hdi_97.5%  mcse_mean  mcse_sd  ess_bulk  ess_tail  r_hat
a_loc         36.174  5.890    23.152     47.541      0.193    0.312    1470.0     707.0   1.00
a_scale       11.903  7.383     4.540     26.831      0.246    0.428    1395.0    1058.0   1.00
b_scale        0.155  0.077     0.054      0.302      0.003    0.004     897.0    1428.0   1.00
g_scale        0.013  0.005     0.006      0.023      0.000    0.000    1019.0     736.0   1.00
h_scale        0.265  0.119     0.108      0.490      0.004    0.007     831.0    1037.0   1.00
v_scale        4.988  3.003     0.322     10.819      0.053    0.044    2372.0    2357.0   1.00
c₁_scale       4.659  3.008     0.277     10.483      0.047    0.046    3365.0    2676.0   1.00
c₂_scale       0.170  0.063     0.075      0.291      0.002    0.002    1161.0    1339.0   1.00
a[0, 0]       31.884  0.452    30.746     32.614      0.014    0.019    2092.0     916.0   1.00
a[0, 1]       31.059  0.515    30.028     32.094      0.009    0.010    4079.0    2101.0   1.00
a[1, 0]       45.450  0.933    43.403     46.469      0.044    0.118    1007.0     480.0   1.01
a[1, 1]       47.838  0.950    46.512     49.720      0.021    0.013    2333.0    2958.0   1.00
a[2, 0]       31.602  0.537    30.765     32.604      0.010    0.006    2839.0    3455.0   1.00
a[2, 1]       32.237  1.401    30.767     33.588      0.124    0.496     871.0     337.0   1.00
b_raw[0, 0]    1.203  0.485     0.306      2.095      0.014    0.008    1131.0    2084.0   1.00
b_raw[0, 1]    0.515  0.249     0.121      1.006      0.007    0.005    1185.0    1605.0   1.00
b_raw[1, 0]    0.713  0.389     0.130      1.492      0.012    0.012    1063.0    1339.0   1.00
b_raw[1, 1]    0.740  0.391     0.128      1.487      0.009    0.009    1410.0    2060.0   1.00
b_raw[2, 0]    1.061  0.440     0.288      1.923      0.012    0.007    1323.0    1711.0   1.00
b_raw[2, 1]    0.438  0.270     0.058      1.004      0.009    0.010    1139.0    1517.0   1.00
g_raw[0, 0]    1.208  0.378     0.475      1.924      0.011    0.007    1039.0     823.0   1.00
g_raw[0, 1]    1.148  0.360     0.458      1.824      0.011    0.007    1036.0     853.0   1.00
g_raw[1, 0]    0.757  0.237     0.305      1.218      0.007    0.004    1049.0     808.0   1.00
g_raw[1, 1]    0.660  0.207     0.282      1.073      0.006    0.004    1026.0     812.0   1.00
g_raw[2, 0]    0.584  0.188     0.221      0.947      0.006    0.003    1042.0     803.0   1.00
g_raw[2, 1]    0.716  0.236     0.267      1.175      0.007    0.004     988.0     801.0   1.00
h_raw[0, 0]    1.038  0.355     0.380      1.745      0.012    0.007     846.0    1012.0   1.00
h_raw[0, 1]    0.827  0.286     0.306      1.412      0.009    0.005     870.0     978.0   1.00
h_raw[1, 0]    0.796  0.290     0.255      1.353      0.009    0.006     924.0    1123.0   1.00
h_raw[1, 1]    0.578  0.217     0.179      0.991      0.006    0.004    1006.0    1162.0   1.00
h_raw[2, 0]    0.827  0.290     0.276      1.388      0.010    0.005     873.0    1107.0   1.00
h_raw[2, 1]    0.948  0.411     0.304      1.808      0.010    0.008    1509.0    1550.0   1.00
v_raw[0, 0]    0.967  0.583     0.092      2.121      0.008    0.009    4051.0    2202.0   1.00
v_raw[0, 1]    0.920  0.591     0.033      2.045      0.009    0.010    3416.0    2355.0   1.00
v_raw[1, 0]    0.645  0.587     0.000      1.773      0.014    0.009     907.0     606.0   1.00
v_raw[1, 1]    0.829  0.601     0.007      1.981      0.009    0.010    3114.0    2119.0   1.00
v_raw[2, 0]    0.878  0.606     0.021      2.039      0.009    0.009    3107.0    1638.0   1.00
v_raw[2, 1]    0.722  0.573     0.000      1.825      0.012    0.009     769.0     319.0   1.01
c₁_raw[0, 0]   0.887  0.591     0.028      1.988      0.008    0.010    3527.0    1908.0   1.00
c₁_raw[0, 1]   0.828  0.596     0.015      1.975      0.008    0.010    3241.0    1838.0   1.00
c₁_raw[1, 0]   0.772  0.622     0.001      1.951      0.010    0.011    2017.0    1187.0   1.00
c₁_raw[1, 1]   0.836  0.592     0.006      1.966      0.009    0.009    3029.0    1482.0   1.00
c₁_raw[2, 0]   0.805  0.583     0.007      1.947      0.009    0.009    3042.0    1951.0   1.00
c₁_raw[2, 1]   0.834  0.610     0.011      2.038      0.009    0.009    3164.0    1830.0   1.00
c₂_raw[0, 0]   0.469  0.168     0.181      0.820      0.004    0.003    1267.0    1439.0   1.00
c₂_raw[0, 1]   0.494  0.179     0.182      0.852      0.005    0.003    1348.0    1542.0   1.00
c₂_raw[1, 0]   0.464  0.181     0.149      0.813      0.005    0.003    1367.0    1742.0   1.00
c₂_raw[1, 1]   0.615  0.234     0.210      1.092      0.006    0.004    1475.0    1833.0   1.00
c₂_raw[2, 0]   0.897  0.320     0.336      1.509      0.009    0.005    1175.0    1408.0   1.00
c₂_raw[2, 1]   1.706  0.527     0.662      2.683      0.014    0.008    1371.0    1764.0   1.00

Visualizing the curves#

# Create prediction dataframe
prediction_df = model.make_prediction_dataset(df=df, num_points=1000)

# Use the model to predict on the prediction dataframe
predictive = model.predict(df=prediction_df, posterior=posterior)

# Create the output directory
current_dir = os.getcwd()
output_dir = os.path.join(current_dir, "hbmep-mixture-extension")
os.makedirs(output_dir, exist_ok=True)

# Plot estimated curves
output_path = os.path.join(output_dir, "curves.pdf")
model.plot_curves(
    df=df,
    prediction_df=prediction_df,
    predictive=predictive,
    posterior=posterior,
    encoder=encoder,
    output_path=output_path
)
../_images/c62c1c3fba02a75b3f53f2d7a9ad4a906fac04fd008410340f1f99ee21449f49.png

We see that the curve for participant P1 and muscle FCR is no longer biased by those few data points, compared to Getting Started. This becomes even clearer when we plot the HDIs around the curves below.

# Plot observations HDI
output_path = os.path.join(output_dir, "obs_hdi.pdf")
model.plot_curves(
    df=df,
    prediction_df=prediction_df,
    predictive=predictive,
    posterior=posterior,
    encoder=encoder,
    output_path="mixture_obs_hdi.pdf",
    predictive_hdi_var=mep.site.obs,
    predictive_hdi_prob=0.95
)
../_images/b36168ec43db42482f24bd29b53f9a5c6d990028c0e82ff1cff60bbe51d6c23a.png