Dear Professor Finn,
Let me know the following formulation works to resolve the particular problem?
P.S. I also conversed with Dr. Rue. But it seems the current INLA version does not support me A.local. I was looking an alternate way to resolve this problem.
"##
set.seed(42)
# ---- Parameters ----
N_img <- 80 # number of distinct images
repeats <- 10 # repeats per image
N_trials <- N_img * repeats
T <- 100 # time bins per trial
grid_size <- 3 # 3x3 grid
# ---- Stimuli X_{n,i,j} ----
# grayscale intensities in [0,1]
X <- array(runif(N_trials * grid_size * grid_size),
dim = c(N_trials, grid_size, grid_size))
# ---- Beta_{i,j,t} ----
# Diagonals: strongly positive constant over time
beta_ijt <- array(0, dim = c(grid_size, grid_size, T))
for (i in 1:grid_size) {
for (j in 1:grid_size) {
if (i == j) {
beta_ijt[i, j, ] <- 2.5 # + rnorm(T, mean = 0, sd = 0.05) # diagonal excitatory
} else {
beta_ijt[i, j, ] <- 0#-1.5 + rnorm(T, mean = 0, sd = 0.05) # off-diagonal inhibitory
}
}
}
# ---- Per-trial random effect b_n ----
b_n <- rnorm(N_trials, mean = 0, sd = 0.1)
# ---- Baseline and simulate y_{n,t} ~ Poisson(exp(linear)) ----
beta0 <- -2
y <- matrix(0, nrow = N_trials, ncol = T)
for (n in 1:N_trials) {
for (t in 1:T) {
lin <- beta0 + b_n[n]
# add spatial contributions
for (i in 1:grid_size) {
for (j in 1:grid_size) {
lin <- lin + beta_ijt[i, j, t] * X[n, i, j]
}
}
lambda_nt <- exp(lin)
y[n, t] <- rpois(1, lambda = lambda_nt)
}
}
# ---- Build dataframe ----
library(dplyr)
df <- expand.grid(
trial = 1:N_trials,
time = 1:T
)
df$y <- as.vector(y)
# ---- Add image_id and rep_id ----
df$image_id <- (df$trial - 1) %/% repeats + 1
df$rep_id <- (df$trial - 1) %% repeats + 1
# ---- Add flattened stimulus features per trial ----
X_mat <- matrix(NA, nrow = N_trials, ncol = grid_size * grid_size)
colnames(X_mat) <- paste0("x_", rep(1:grid_size, each = grid_size), "_", rep(1:grid_size, times = grid_size))
for (n in 1:N_trials) {
X_mat[n, ] <- as.vector(t(X[n, , ]))
}
df <- cbind(df, df$trial %>% sapply(function(tr) X_mat[tr, ]) %>% t())
colnames(df)[(ncol(df) - ncol(X_mat) + 1):ncol(df)] <- colnames(X_mat)
# ---- Quick check ----
mean_beta <- apply(beta_ijt, c(1, 2), mean)
print("Mean beta (3x3): diagonals should be large positive:")
print(round(mean_beta, 3))
diag_means <- diag(mean_beta)
offdiag_means <- mean(mean_beta[upper.tri(mean_beta) | lower.tri(mean_beta)])
cat("Diagonal means:", round(diag_means, 3), "\n")
cat("Average off-diagonal mean:", round(offdiag_means, 3), "\n")
cat("Overall mean spike count:", mean(df$y), " (sd:", sd(df$y), ")\n")
# ---- Optional: visualize beta ----
image(1:3, 1:3, mean_beta, main = "Mean β across pixels", xlab = "i", ylab = "j")
contour(1:3, 1:3, mean_beta, add = TRUE)
# ---- Check new columns ----
head(df)
### getting estimated by spde , model recovery
df_real <- df %>%
rename(
time_bin_num = time,
firing_count = y
)
df <- df_real
library(INLA)
library(Matrix)
# Identify pixel columns
pixel_cols <- grep("^x_\\d+_\\d+$", colnames(df), value = TRUE)
# Extract pixel coordinates
pixel_coords <- do.call(rbind, lapply(pixel_cols, function(name) {
x <- as.numeric(sub("^x_(\\d+)_\\d+$", "\\1", name))
y <- as.numeric(sub("^x_\\d+_(\\d+)$", "\\1", name))
c(x, y)
}))
colnames(pixel_coords) <- c("x", "y")
# Build SPDE mesh
mesh <- inla.mesh.2d(loc = pixel_coords, max.edge = c(1, 1), cutoff = 0.01)
spde <- inla.spde2.matern(mesh = mesh, alpha = 2)
# Projector matrix for pixels
A_pix <- inla.spde.make.A(mesh = mesh, loc = pixel_coords)
# Observation × SPDE design
X_spatial <- as.matrix(df[, pixel_cols]) %*% A_pix
# INLA stack with rep_id
stack <- inla.stack(
data = list(y = df$firing_count),
A = list(1, X_spatial, 1), # intercept + spatial field + rep_id
effects = list(
intercept = rep(1, nrow(df)),
spatial_field = 1:spde$n.spde,
rep_id = df$rep_id # include rep_id here
),
tag = "spatial_stack"
)
# Assuming 'time_col' is the column in df representing time (t)
# Formula including rep_id as IID random effect
formula <- y ~ 1 +
f(rep_id, model = "iid") +
f(spatial_field, model = spde)
# Fit the model
result <- inla(
formula,
data = inla.stack.data(stack),
family = "poisson",
control.predictor = list(A = inla.stack.A(stack), compute = TRUE),
control.compute = list(dic = TRUE, waic = TRUE, config = TRUE),
control.inla = list(strategy = "simplified.laplace")
)
# Posterior mean of spatial field ## beta retrival?
field_mean <- result$summary.random$spatial_field$mean