The PKPD Meta 105: Single-Patient Bayesian Workflow walkthrough demonstrated the CmdStanPy pipeline on a single synthetic retina subject. This follow-up moves the exact stand_ode model into RStan, keeps the original patient as a reference point, and adds a second longitudinal BCVA record to expose the population signal. The companion notebook stand-ode-rstan-demo.ipynb captures the full analysis; the highlights below surface the evidence without opening the notebook.

Notebook setup

The RStan check confirms stan_ode.stan compiles in-place and shows the generated C++ model. Those diagnostics mirror the single-patient post, but now we retain them as a baseline before layering multiple patients.

Loading required package: StanHeaders

rstan version 2.32.7 (Stan version 2.32.2)
...
S4 class stanmodel 'anon_model' coded as follows:
functions {
  vector drug_disease_stim_kinL_Et_ode(real t,
                                       vector y,
                                       array[] real theta,
                                       array[] real x_r,
                                       array[] int x_i) {
    ...

Synthetic BCVA inputs

Both patients follow the six-visit schedule introduced in CI 105, with patient two starting higher on the BCVA scale to emphasize the population spread.

patient_idtimebcva
patient_01045.0
patient_01747.5
patient_011450.0
patient_012854.0
patient_015657.0
patient_018458.5
patient_02052.0
patient_02754.0
patient_021456.5
patient_022860.0
patient_025663.0
patient_028464.0

Patient-level posterior summaries

Each patient fits the existing ODE independently. The posterior means highlight how the dosing parameters shift once we expose the model to the higher-BCVA subject.

patient_idparametermeansdn_effrhat
patient_01k_in0.0110.0023350.01.022
patient_01k_out0.0330.0062474.71.010
patient_01emax00.7180.3055520.31.012
patient_01lec502.2120.4108253.71.026
patient_01sigma0.6580.5107302.71.003
patient_01R0-0.2170.0273662.31.000
patient_02k_in0.0180.004680.51.051
patient_02k_out0.0330.0069374.31.011
patient_02emax00.7120.2921613.91.005
patient_02lec502.1620.4408177.11.025
patient_02sigma0.7320.5340348.91.008
patient_02R00.0560.0300412.61.008

The jump in k_in captures a faster recovery rate for patient_02, while the shared k_out reinforces that the ODE structure is unchanged from the single-subject run.

Sampling diagnostics

Running identical priors on multiple subjects surfaces the divergences we would want to address before calling this population-ready. Keeping the warning text in the post helps reviewers see exactly what the notebook surfaced.

Warning message:
“There were 7 divergent transitions after warmup. See
https://mc-stan.org/misc/warnings.html#divergent-transitions-after-warmup
to find out why this is a problem and how to eliminate them.”
Warning message:
“Bulk Effective Samples Size (ESS) is too low, indicating posterior means and medians may be unreliable.
Running the chains for more iterations may help.”

These diagnostics mirror the challenges from fitting patient_01 alone and underline why a true population model would introduce partial pooling rather than copying the single-patient priors verbatim.

Posterior trajectories across patients

Two panels showing posterior predictive BCVA trajectories against observed data for patient_01 and patient_02.
Posterior predictive BCVA curves for each patient. The wider ribbons for patient_02 trace the higher initial BCVA and faster improvement that the single-patient workflow could not reveal.

The twin panels juxtapose each subject’s posterior predictive BCVA path against the observed visits. This is the visual cue that the population contains more variability than the single-subject story.

Aggregating to a population view

Taking the mean of the posterior predictions at every visit offers a crude population signal. It underlines how pooling two patients smooths uncertainty and shifts the expected BCVA improvement upward relative to the original single-patient fit.

timepopulation_meanpopulation_lowerpopulation_upper
048.0246.2949.48
751.1449.8452.60
1453.5852.3755.09
2856.9355.6158.57
5660.0658.6361.54
8461.0959.3562.60

+++