data_path = "../../data/human_data/prediction/experiment_2.db"
con = dbConnect(RSQLite::SQLite(), data_path)
tables = dbListTables(con)
df = dbGetQuery(con, "SELECT * FROM plinko")
dbDisconnect(con)df_pred_demo = df %>%
filter(mode == "live",
status >= 3,
codeversion == "experiment_2") %>%
mutate(part_num = seq(1, nrow(.)),
data_json = map(.x = datastring,
.f = fromJSON),
question_data = map(.x = data_json,
.f = ~ .$questiondata),
gender = as.character(map(.x = question_data,
.f = ~ .$sex)),
age = as.numeric(map(.x = question_data,
.f = ~ .$age))) %>%
select(part_num, gender, age)## mean_age sd_age
## 1 37 11
df_human_means = read.csv("../python/prediction/human_mean_ci.csv") %>%
rename(human_mean = mean_response)
df_sim_means = read.csv("../python/prediction/saved_model_pred/noisy_sim_mean.csv") %>%
rename(sim_mean = mean)
df_model_data = df_human_means %>%
left_join(df_sim_means,
by = c("world", "hole")) %>%
mutate(hole = as.factor(hole))df_sum_stat = df_model_data %>%
summarise(r = round(cor(sim_mean, human_mean), 2),
rmse = round(sqrt(mean((sim_mean - human_mean)^2)), 2))
df_emph_trial = df_model_data %>%
filter(world == 70)
ggplot(data=df_model_data,
mapping = aes(x = sim_mean,
y = human_mean)) +
geom_abline(intercept = 0, slope = 1, linetype = "dashed") +
geom_linerange(mapping = aes(ymin = ci_lower,
ymax = ci_upper)) +
geom_point(mapping=aes(fill=hole),
shape=21,
color="black",
size=1) +
geom_point(data = df_emph_trial,
mapping = aes(fill=hole),
shape=23,
color="black",
size=3) +
geom_text(data = df_sum_stat,
mapping = aes(x = 0, y = 580, label = paste("r = ", r)),
hjust=0,
size = 4) +
geom_text(data = df_sum_stat,
mapping = aes(x = 0, y = 540, label = paste("RMSE = ", rmse)),
hjust=0,
size = 4) +
scale_fill_manual(values = custom_colors) +
scale_x_continuous(breaks = c(0, 200, 400, 600),
labels = function(x) paste0(x, "px"),
limits = c(0,600)) +
scale_y_continuous(breaks = c(0, 200, 400, 600),
labels = function(x) paste0(x, "px"),
limits=c(0,600)) +
labs(x = "Simulator Mean Prediction",
y = "Human Mean Prediction") +
theme(legend.position = "none",
axis.text = element_text(size = 10),
axis.title = element_text(size = 12))df_human_judgment_vision = read.csv("../../data/human_data/inference/vision_judge_summary_rt_cleaned.csv")
df_human_judgment_audio = read.csv("../../data/human_data/inference/audio_judge_summary_rt_cleaned.csv")
df_human_judgment_occluded = read.csv("../../data/human_data/inference/occluded_judge_summary_rt_cleaned.csv")
df_sequential_judgment_vision = read.csv("../python/inference/model_performance/top_models/sequential_top_vision_judgment.csv")
df_sequential_judgment_audio = read.csv("../python/inference/model_performance/top_models/sequential_top_audio_judgment.csv")
df_sequential_judgment_occluded = read.csv("../python/inference/model_performance/top_models/sequential_top_occluded_judgment.csv")
df_uniform_judgment_vision = read.csv("../python/inference/model_performance/top_models/uniform_top_vision_judgment.csv")
df_uniform_judgment_audio = read.csv("../python/inference/model_performance/top_models/uniform_top_audio_judgment.csv")
df_uniform_judgment_occluded = read.csv("../python/inference/model_performance/top_models/uniform_top_occluded_judgment.csv")
df_comp_sequential_judgment_vision = df_human_judgment_vision %>%
left_join(df_sequential_judgment_vision,
by = c("trial", "hole")) %>%
mutate("condition" = "vision")
df_comp_sequential_judgment_audio = df_human_judgment_audio %>%
left_join(df_sequential_judgment_audio,
by = c("trial", "hole")) %>%
mutate("condition" = "audio")
df_comp_sequential_judgment_occluded = df_human_judgment_occluded %>%
left_join(df_sequential_judgment_occluded,
by = c("trial", "hole")) %>%
mutate("condition" = "occluded")
df_comp_sequential_judgment = bind_rows(df_comp_sequential_judgment_vision,
df_comp_sequential_judgment_audio,
df_comp_sequential_judgment_occluded) %>%
mutate(hole = as.factor(hole),
condition = factor(condition,
levels=c("vision", "audio", "occluded"),
labels=c("No Sound + Ball Visible", "Sound + Ball Visible", "Sound + Ball Occluded")),
Model = "Sequential Sampler")
df_comp_uniform_judgment_vision = df_human_judgment_vision %>%
left_join(df_uniform_judgment_vision,
by = c("trial", "hole")) %>%
mutate("condition" = "vision")
df_comp_uniform_judgment_audio = df_human_judgment_audio %>%
left_join(df_uniform_judgment_audio,
by = c("trial", "hole")) %>%
mutate("condition" = "audio")
df_comp_uniform_judgment_occluded = df_human_judgment_occluded %>%
left_join(df_uniform_judgment_occluded,
by = c("trial", "hole")) %>%
mutate("condition" = "occluded")
df_comp_uniform_judgment = bind_rows(df_comp_uniform_judgment_vision,
df_comp_uniform_judgment_audio,
df_comp_uniform_judgment_occluded) %>%
mutate(hole = as.factor(hole),
condition = factor(condition,
levels=c("vision", "audio", "occluded"),
labels=c("No Sound + Ball Visible", "Sound + Ball Visible", "Sound + Ball Occluded")),
Model = "Uniform Sampler")df_to_show = rbind(
df_comp_sequential_judgment,
df_comp_uniform_judgment
)
df_metrics = df_to_show %>%
mutate(model_y = model_y*100,
data_y = data_y*100) %>%
group_by(condition, Model) %>%
summarise(r = round(cor(model_y, data_y), 2),
rmse = round(rmse(data_y, model_y), 2))## `summarise()` has grouped output by 'condition'. You can override using the
## `.groups` argument.
condition_colors = c("tomato2", "darkorange2", "gold2")
ggplot(data=df_to_show,
mapping = aes(x = model_y,
y = data_y)) +
geom_abline(intercept = 0, slope = 1, linetype = "dashed") +
geom_linerange(mapping = aes(ymin = lower,
ymax = upper),
color = "black",
alpha=0.2) +
geom_point(mapping = aes(fill=hole),
shape=21,
color="black") +
geom_text(data = df_metrics,
mapping = aes(x = 0, y = 1, label = paste("r = ", r)),
hjust=0,
size = 6) +
geom_text(data = df_metrics,
mapping = aes(x = 0, y = 0.92, label = paste("RMSE = ", rmse)),
hjust=0,
size = 6) +
facet_grid2(Model ~ condition,
strip = strip_themed(
background_x = list(
element_rect(fill = condition_colors[1]),
element_rect(fill = condition_colors[2]),
element_rect(fill = condition_colors[3])
))) +
scale_fill_manual(values = custom_colors) +
scale_x_continuous(labels = percent_format(accuracy = 1)) +
scale_y_continuous(labels = percent_format(accuracy = 1)) +
labs(x = "Precentage Predicted",
y = "Percentage Selected") +
theme(legend.position = "none",
axis.text = element_text(size = 22),
axis.title = element_text(size = 26),
strip.text = element_text(size = 26),
panel.spacing.x=unit(2, "cm"),
panel.spacing.y=unit(1, "cm"))df_human_judgment = rbind(
df_human_judgment_vision %>%
mutate(condition = "vision"),
df_human_judgment_audio %>%
mutate(condition = "audio"),
df_human_judgment_occluded %>%
mutate(condition = "occluded")
)
df_human_judgment %>%
filter(trial == 1) %>%
mutate(percent = round(data_y*100))## trial hole data_y lower upper condition percent
## 1 1 0 0.00000000 0.0000000 0.0000000 vision 0
## 2 1 1 0.96666667 0.9000000 1.0000000 vision 97
## 3 1 2 0.03333333 0.0000000 0.1000000 vision 3
## 4 1 0 0.23333333 0.1000000 0.4000000 audio 23
## 5 1 1 0.06666667 0.0000000 0.1666667 audio 7
## 6 1 2 0.70000000 0.5333333 0.8333333 audio 70
## 7 1 0 0.40000000 0.2333333 0.6000000 occluded 40
## 8 1 1 0.00000000 0.0000000 0.0000000 occluded 0
## 9 1 2 0.60000000 0.4000000 0.7666667 occluded 60
plot_trial_bar = function(df_human_judgment, trial_id, cond) {
color_map = c("vision" = "tomato2",
"audio" = "darkorange2",
"occluded" = "gold2")
df_to_show = df_human_judgment %>%
filter(trial == trial_id,
condition == cond) %>%
mutate(hole = factor(hole,
levels = c(0,1,2),
labels = c(1,2,3)))
ggplot(data = df_to_show,
mapping = aes(x = hole,
y = data_y)) +
geom_bar(stat = "identity",
fill = color_map[cond],
color = "black",
alpha = 0.7) +
geom_linerange(mapping = aes(ymin = lower,
ymax = upper),
color = "black") +
xlab("Hole") +
scale_x_discrete(labels=c("1", "2", "3")) +
ylab(NULL) +
scale_y_continuous(labels = percent_format(),
limits = c(0,1)) +
theme(axis.text = element_text(size = 22),
axis.title = element_text(size = 26))
}df_emd_sequential_vision =
read.csv("../python/inference/model_performance/top_models/sequential_top_vision_emd.csv") %>%
mutate(model = "sequential",
condition = "vision")
df_emd_sequential_audio =
read.csv("../python/inference/model_performance/top_models/sequential_top_audio_emd.csv") %>%
mutate(model = "sequential",
condition = "audio")
df_emd_sequential_occluded =
read.csv("../python/inference/model_performance/top_models/sequential_top_occluded_emd.csv") %>%
mutate(model = "sequential",
condition = "occluded")
df_emd_uniform_vision = read.csv("../python/inference/model_performance/top_models/uniform_top_vision_emd.csv") %>%
mutate(model = "uniform",
condition = "vision")
df_emd_uniform_audio = read.csv("../python/inference/model_performance/top_models/uniform_top_audio_emd.csv") %>%
mutate(model = "uniform",
condition = "audio")
df_emd_uniform_occluded = read.csv("../python/inference/model_performance/top_models/uniform_top_occluded_emd.csv") %>%
mutate(model = "uniform",
condition = "occluded")
df_emd_visual_features_vision = read.csv("../python/inference/model_performance/emd/visual_features_vision_emd.csv") %>%
mutate(model = "visual_features",
condition = "vision")
df_emd_visual_features_audio = read.csv("../python/inference/model_performance/emd/visual_features_audio_emd.csv") %>%
mutate(model = "visual_features",
condition = "audio")
df_emd_visual_features_occluded = read.csv("../python/inference/model_performance/emd/visual_features_occluded_emd.csv") %>%
mutate(model = "visual_features",
condition = "occluded")
df_emd_baseline_vision = read.csv("../python/inference/model_performance/emd/baseline_uniform_vision_emd.csv") %>%
mutate(model = "baseline",
condition = "vision")
df_emd_baseline_audio = read.csv("../python/inference/model_performance/emd/baseline_uniform_audio_emd.csv") %>%
mutate(model = "baseline",
condition = "audio")
df_emd_baseline_occluded = read.csv("../python/inference/model_performance/emd/baseline_uniform_occluded_emd.csv") %>%
mutate(model = "baseline",
condition = "occluded")
df_emd_baseline = bind_rows(df_emd_baseline_vision,
df_emd_baseline_audio,
df_emd_baseline_occluded) %>%
group_by(condition) %>%
summarise(mean_dist = mean(distance)) %>%
mutate(condition = factor(condition,
levels = c("vision", "audio", "occluded"),
labels = c("No Sound + Ball Visible", "Sound + Ball Visible", "Sound + Ball Occluded"))) %>%
arrange(condition)
set.seed(5)
df_emd = bind_rows(
df_emd_sequential_vision,
df_emd_sequential_audio,
df_emd_sequential_occluded,
df_emd_uniform_vision,
df_emd_uniform_audio,
df_emd_uniform_occluded,
df_emd_visual_features_vision,
df_emd_visual_features_audio,
df_emd_visual_features_occluded) %>%
mutate(x_pos = case_when(
model == "sequential" ~ 0,
model == "uniform" ~ 1,
model == "visual_features" ~ 2
),
x_pos = x_pos + rnorm(nrow(.), sd = 0.1),
condition = factor(condition,
levels=c("vision", "audio", "occluded"),
labels=c("No Sound + Ball Visible", "Sound + Ball Visible", "Sound + Ball Occluded")),
highlight = trial == 20,
x_pos = ifelse(model == "sequential" & highlight, 0, x_pos),
x_pos = ifelse(model == "uniform" & highlight, 1, x_pos),
x_pos = ifelse(model == "visual_features" & highlight, 2, x_pos),
model = factor(model,
levels=c("sequential", "uniform", "visual_features"),
labels=c(0,1,2)),
model = as.numeric(as.character(model)))
df_highlight = df_emd %>%
filter(highlight)
df_label = data.frame(
x = -0.35,
y = 115,
label = "Baseline",
condition = "No Sound + Ball Visible"
) %>%
mutate(condition = factor(condition))ggplot(data=df_emd,
mapping = aes(x=model,
y=distance)) +
geom_hline(data = df_emd_baseline,
mapping = aes(yintercept = mean_dist),
linetype = "dashed",
alpha=0.5) +
stat_summary(fun = "mean",
geom = "bar",
fill = "wheat1",
color = "black",
width=0.8) +
stat_summary(fun.data = "mean_cl_boot",
geom = "linerange",
color = "black") +
geom_point(mapping = aes(x=x_pos),
alpha=0.1) +
geom_point(data = df_highlight,
mapping = aes(x = x_pos),
size = 2) +
geom_text(data = df_label,
mapping = aes(x = x,
y = y,
label = label),
inherit.aes = FALSE,
hjust = 0,
vjust = 0,
size = 6) +
facet_wrap2(~condition,
ncol=3,
strip = strip_themed(
background_x = list(
element_rect(fill = condition_colors[1]),
element_rect(fill = condition_colors[2]),
element_rect(fill = condition_colors[3])
))) +
scale_x_continuous(breaks = c(0,1,2),
labels = c("Sequential\nSampler", "Uniform\nSampler", "Visual\nFeatures")) +
scale_y_continuous(breaks = c(50, 100, 150)) +
labs(x = "Model",
y = "Earth Mover's Distance") +
theme(axis.text.x = element_text(size = 22),
axis.text.y = element_text(size = 22),
axis.title.x = element_text(size = 26,
margin = margin(t=15)),
axis.title.y = element_text(size = 26),
strip.text = element_text(size = 26),
panel.spacing = unit(2, "cm"))## `summarise()` has grouped output by 'model'. You can override using the
## `.groups` argument.
## # A tibble: 9 × 3
## # Groups: model [3]
## model condition mean_distance
## <dbl> <fct> <dbl>
## 1 0 No Sound + Ball Visible 53.1
## 2 0 Sound + Ball Visible 54.4
## 3 0 Sound + Ball Occluded 44.4
## 4 1 No Sound + Ball Visible 72.5
## 5 1 Sound + Ball Visible 70.4
## 6 1 Sound + Ball Occluded 44.9
## 7 2 No Sound + Ball Visible 79.3
## 8 2 Sound + Ball Visible 79.2
## 9 2 Sound + Ball Occluded 57.3
df_gt = read.csv("../../data/stimuli/inference/drop_gt.csv") %>%
mutate(gt_hole = hole + 1) %>%
select(trial, gt_hole)
df_human_select_vision = read.csv("../../data/human_data/inference/vision_judgment_rt_cleaned.csv") %>%
select(-X) %>%
left_join(df_gt,
by = "trial") %>%
mutate(correct = (response == gt_hole)*1)
df_human_select_audio = read.csv("../../data/human_data/inference/audio_judgment_rt_cleaned.csv") %>%
select(-X) %>%
left_join(df_gt,
by = "trial") %>%
mutate(correct = (response == gt_hole)*1,
experiment = "audio")
df_human_select_occluded = read.csv("../../data/human_data/inference/occluded_judgment_rt_cleaned.csv") %>%
select(-X) %>%
left_join(df_gt,
by = "trial") %>%
mutate(correct = (response == gt_hole)*1)boot_prop_ci <- function(df_select, R = 1000, conf = 0.95) {
correct = df_select$correct
stopifnot(all(correct %in% c(0,1)))
p_hat <- mean(correct)
boots <- replicate(R, {
mean(sample(correct, size = length(correct), replace = TRUE))
})
alpha <- (1 - conf) / 2
ci <- as.numeric(quantile(boots, probs = c(alpha, 1 - alpha), names = FALSE))
list(
estimate = round(p_hat, 2),
lower = round(ci[1], 2),
upper = round(ci[2], 2),
conf = conf
)
}## $estimate
## [1] 0.72
##
## $lower
## [1] 0.71
##
## $upper
## [1] 0.73
##
## $conf
## [1] 0.95
## $estimate
## [1] 0.78
##
## $lower
## [1] 0.77
##
## $upper
## [1] 0.79
##
## $conf
## [1] 0.95
occ_fit = brm(correct ~ 1 + (1|participant) + (1|trial),
data = df_human_select_occluded,
family = bernoulli(),
cores = 4,
seed = 1,
file = "fits/occ_fit.rds")## Family: bernoulli
## Links: mu = logit
## Formula: correct ~ 1 + (1 | participant) + (1 | trial)
## Data: df_human_select_occluded (Number of observations: 4481)
## Draws: 4 chains, each with iter = 2000; warmup = 1000; thin = 1;
## total post-warmup draws = 4000
##
## Multilevel Hyperparameters:
## ~participant (Number of levels: 30)
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept) 0.61 0.10 0.45 0.82 1.00 959 1682
##
## ~trial (Number of levels: 150)
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept) 1.92 0.13 1.69 2.20 1.00 704 1139
##
## Regression Coefficients:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## Intercept 0.93 0.20 0.52 1.32 1.01 452 769
##
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Convert samples to probability scale
post = as_draws_df(occ_fit)
prob = plogis(post$b_Intercept)
round(quantile(prob, c(0.025, 0.5, 0.975)), 2)## 2.5% 50% 97.5%
## 0.63 0.72 0.79
## 5%
## 0.64
## [1] 1
df_human_select_comb = rbind(
df_human_select_vision,
df_human_select_audio,
df_human_select_occluded
) %>%
rename(condition = experiment)cond_fit = brm(correct ~ condition + (1|participant) + (1|trial),
data = df_human_select_comb,
family = bernoulli(),
cores = 4,
seed = 1,
file = "fits/cond_fit.rds")## Family: bernoulli
## Links: mu = logit
## Formula: correct ~ condition + (1 | participant) + (1 | trial)
## Data: df_human_select_comb (Number of observations: 13321)
## Draws: 4 chains, each with iter = 2000; warmup = 1000; thin = 1;
## total post-warmup draws = 4000
##
## Multilevel Hyperparameters:
## ~participant (Number of levels: 31)
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept) 0.35 0.06 0.26 0.48 1.00 1131 1965
##
## ~trial (Number of levels: 150)
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept) 1.12 0.07 0.98 1.27 1.00 862 1633
##
## Regression Coefficients:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## Intercept 1.58 0.12 1.34 1.81 1.01 492 939
## conditionoccluded -0.86 0.05 -0.97 -0.76 1.00 4782 3136
## conditionvision -0.38 0.05 -0.48 -0.27 1.00 4465 3050
##
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
hyps = c(
hyp1 = "0 - conditionvision > 0",
hyp2 = "conditionvision - conditionoccluded > 0",
hyp3 = "0 - conditionoccluded > 0"
)
hypothesis(cond_fit, hyps, alpha = 0.025)## Hypothesis Tests for class b:
## Hypothesis Estimate Est.Error CI.Lower CI.Upper Evid.Ratio Post.Prob Star
## 1 hyp1 0.38 0.05 0.27 0.48 Inf 1 *
## 2 hyp2 0.48 0.05 0.39 0.58 Inf 1 *
## 3 hyp3 0.86 0.05 0.76 0.97 Inf 1 *
## ---
## 'CI': 95%-CI for one-sided and 97.5%-CI for two-sided hypotheses.
## '*': For one-sided hypotheses, the posterior probability exceeds 97.5%;
## for two-sided hypotheses, the value tested against lies outside the 97.5%-CI.
## Posterior probabilities of point hypotheses assume equal prior probabilities.
## R version 4.5.0 (2025-04-11)
## Platform: aarch64-apple-darwin20
## Running under: macOS Sequoia 15.6.1
##
## Matrix products: default
## BLAS: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRblas.0.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.12.1
##
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
##
## time zone: America/Los_Angeles
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] lubridate_1.9.4 forcats_1.0.0 stringr_1.5.1 dplyr_1.1.4
## [5] purrr_1.1.0 readr_2.1.5 tidyr_1.3.1 tibble_3.2.1
## [9] tidyverse_2.0.0 brms_2.22.0 Rcpp_1.0.14 broom_1.0.8
## [13] scales_1.4.0 ggnewscale_0.5.2 ggh4x_0.3.1 ggplot2_4.0.0
## [17] Metrics_0.1.4 jsonlite_2.0.0 RSQLite_2.4.3 DBI_1.2.3
## [21] knitr_1.50
##
## loaded via a namespace (and not attached):
## [1] gridExtra_2.3 inline_0.3.21 rlang_1.1.6
## [4] magrittr_2.0.3 matrixStats_1.5.0 compiler_4.5.0
## [7] loo_2.8.0 reshape2_1.4.4 systemfonts_1.2.3
## [10] vctrs_0.6.5 pkgconfig_2.0.3 fastmap_1.2.0
## [13] backports_1.5.0 labeling_0.4.3 utf8_1.2.5
## [16] rmarkdown_2.29 tzdb_0.5.0 ragg_1.4.0
## [19] bit_4.6.0 xfun_0.52 cachem_1.1.0
## [22] blob_1.2.4 parallel_4.5.0 cluster_2.1.8.1
## [25] R6_2.6.1 bslib_0.9.0 stringi_1.8.7
## [28] RColorBrewer_1.1-3 StanHeaders_2.32.10 rpart_4.1.24
## [31] jquerylib_0.1.4 estimability_1.5.1 bookdown_0.43
## [34] rstan_2.32.7 base64enc_0.1-3 bayesplot_1.12.0
## [37] Matrix_1.7-3 nnet_7.3-20 timechange_0.3.0
## [40] tidyselect_1.2.1 rstudioapi_0.17.1 abind_1.4-8
## [43] yaml_2.3.10 codetools_0.2-20 pkgbuild_1.4.8
## [46] plyr_1.8.9 lattice_0.22-6 withr_3.0.2
## [49] bridgesampling_1.1-2 S7_0.2.0 posterior_1.6.1
## [52] coda_0.19-4.1 evaluate_1.0.3 foreign_0.8-90
## [55] RcppParallel_5.1.10 pillar_1.10.2 tensorA_0.36.2.1
## [58] checkmate_2.3.2 stats4_4.5.0 distributional_0.5.0
## [61] generics_0.1.4 hms_1.1.3 rstantools_2.4.0
## [64] xtable_1.8-4 glue_1.8.0 emmeans_1.11.1
## [67] Hmisc_5.2-3 tools_4.5.0 data.table_1.17.4
## [70] mvtnorm_1.3-3 grid_4.5.0 QuickJSR_1.7.0
## [73] colorspace_2.1-1 nlme_3.1-168 htmlTable_2.4.3
## [76] Formula_1.2-5 cli_3.6.5 textshaping_1.0.1
## [79] Brobdingnag_1.2-9 gtable_0.3.6 sass_0.4.10
## [82] digest_0.6.37 htmlwidgets_1.6.4 farver_2.1.2
## [85] memoise_2.0.1 htmltools_0.5.8.1 lifecycle_1.0.4
## [88] bit64_4.6.0-1