CmdStan, CmdStanR, CmdStanPy workflow resulting in errors with `as.shinystan` function

My model successfully runs and produces CSV files. However, when trying to use R and ShinyStan, I am unable to get ShinyStan to accept my model files using CmdStanR. I have been digging into the documentation and it looks like ShinyStan added support for CmdStanR objects about 3 years ago. It should work from what I can see. However, the output signature returned for as_cmdstan_fit is supposed to be CmdStanMCMC but is CmdStanMCMC_CSV. And then when using read_cmdstan_csv it creates a list which is a type as.shinystan can take. However, the list is not structured the way as.shinystan expects so it errors out with the elements of X should be matrices (…) error.

I would appreciate any help, suggestions, etc that could be provided. If this is a bug I am happy to submit a bug report to the appropriate repo. However, I’m guessing this is a problem with my workflow/code.

My model is relatively basic and shown below.

// Stan Model for adjusted model

data {
  int<lower=1> C; 
  int<lower=1> T; 
  vector[C] x;
  array[T] vector[C] N; 
  array[T, C] int<lower=0> y; 
  array[T] matrix[C, C] w;
}
parameters {
  vector[C] alpha_foo;
  real alpha_bar;
  real <lower=0> alpha_dev;
  real beta;
}
transformed parameters {
  vector[C] alpha = alpha_bar + alpha_foo * alpha_dev;
  vector[C] exp_terms = exp(alpha + beta * x);
}
model {
  /*--- Hyper Parameters ---*/
  alpha_foo ~ normal(0, 1);
  alpha_bar ~ normal(log(42), 0.2);
  alpha_dev ~ normal(0, 0.1);
  beta ~ normal(1, 1);
  /*--- Model Logic ---*/
  for (t in 1 : T) {
    // loop through time
    vector[C] lambda_t = N[t] .* ((w[t] * exp_terms)/10^5); //scale to 100K
    y[t] ~ poisson(lambda_t); // model shit
  }
}

I developed some Python code to clean/format my data and then used CmdStanPy to run my Stan model with a save directory for the output CSV files. The CmdStanPy call is shown below.

    [...]
    sampled_stan = _model.sample(
        data=sample_data,
        iter_sampling=cfg_raw.stan.iterations | 1000,
        iter_warmup=cfg_raw.stan.burn_in | 1000,
        threads_per_chain=1,
        chains=threads,
        max_treedepth=12,
        parallel_chains=threads,
        output_dir=output_dir,
        save_warmup=cfg_raw.stan.diagnostics,
    )

To poke around the results, as I am relatively new to Stan, I wanted to use ShinyStan. Using the code I provided below I attempted to do just that.

library(shinystan)
library(cmdstanr)


files <- list.files(
  path="model/support_logic/.sim_save",
  pattern="\\.csv$",
  full.names = TRUE
)

# fit <- read_cmdstan_csv(
#   files,
#   #check_diagnostics = TRUE,
#   format = getOption("cmdstanr_draws_format")
# )

fit <- as_cmdstan_fit(
  files,
  check_diagnostics = TRUE,
  format = getOption("cmdstanr_draws_format")
)

shiny <- as.shinystan(fit)

launch_shinystan(shiny)

However, when using as_cmdstan_fit as shown above, I get the following error:

r$> source("/Volumes/WorkFiles/[...]/pystansim/shinystan.r", encoding = "UTF-8")
Error: unable to find an inherited method for function 'as.shinystan' for signature 'X = "CmdStanMCMC_CSV"'

If the as_cmdstan_fit block is commented out and I use read_cmdstan_csv instead I get the following error:

Error in .local(X, ...) :
  All elements of X should be matrices / 2-D arrays.

Data is under DUA so I can’t provide any portions or snippets. However, here is some code to produce toy data that is compatible:

import numpy as np
from cmdstanpy import CmdStanModel

C = 10 
T = 15 

x = np.linspace(0.1, 1.0, C)

N = [np.random.poisson(20000, size=C) for _ in range(T)]  # shape (T, C)

y = np.array([[np.random.poisson(100) for _ in range(C)] for _ in range(T)], dtype=int)

w = [np.eye(C) * 0.5 + np.random.rand(C, C) * 0.5 for _ in range(T)]  # random CxC

stan_data = {
    "C": C,
    "T": T,
    "x": x,  
    "N": N,  
    "y": y, 
    "w": w,
}


model = CmdStanModel(stan_file="./adjusted.stan")

# Sample
fit = model.sample(data=stan_data, chains=8, iter_sampling=1000, iter_warmup=10000)
print(fit.summary())

Please provide this additional information in addition to your question:

  • Operating System: MacOS 26.1
  • CmdStan Version: 2.37.0
  • Compiler/Toolkit: Clang 15.0.0 (clang-1500.3.9.4), Xcode Toolkit

Turns out there’s a cursed answer to this:

# Load objects from a set of .csv files:
m = cmdstanr::as_cmdstan_fit(files = fs::dir_ls('.', regex = 'var-model--output.*'))

library(shinystan)

# Drop the class name interfering with the shinystan function
class(m) = class(m)[2:4]

# Add a function ShinyStan expects
m$runset$model_name = function() "model"

# Now these work good
shinystan::as.shinystan(m)
shinystan::launch_shinystan(m)
2 Likes

I need to do a shinystan release this winter in order to change the maintainer email address with CRAN. I’ll try to look into this and see if I can get it working properly before I do the release.

1 Like

Thanks for looking into it!

1 Like

Also @danni_storm, since you’re actually fitting your models in Python, you could try out

which isn’t exactly the same as ShinyStan but provides some similar functionality. You wouldn’t need to import anything into R after running Python.

1 Like