
getwd()
rm(list = ls())
source('./src/data_pattern_generator.R')
load('./data/lgcp_data_full.RData')
library(FNN)
library(dplyr)

#----------------------- Get lgcp data ---------------------------
# Data pattern generation
domain_max = 10
win <- owin(c(0,domain_max), c(0,domain_max))
square_boundary <- matrix(c(0, 0, 10, 0, 10, 10, 0, 10, 0, 0), ncol = 2, byrow = TRUE)
spatstat.options(npixel = 21*21)
# spatstat.options(npixel = 21*21)
y0 = x0 = seq(win$xrange[1], win$xrange[2], length = spatstat.options()$npixel)
pl.dom_hole = cbind(c(2, 8, 8, 2), c(2, 2, 8.5, 8.5))

xy.c_observed = DP_with_hole1$xy_c_observed
# N = length(xy.c_observed)
# n_hole = mesh_hole$n
# N_hole = dim(xy.c_observed)[1]

lg.s.c = DP_without_hole1$lg_s_c
lambda_values <- attr(lg.s.c, 'Lambda')
lambda_values$v = log(lambda_values$v)
log_intensity_value = lambda_values$v

dual_mesh_plot = inla.mesh.dual(mesh_full)


# mask
n_total <- nrow(xy.c_observed)
n_remain <- round(n_total * 0.80)
indices_remain <- sample(1:n_total, size = n_remain, replace = FALSE)
xy.c_observed_remain <- xy.c_observed[indices_remain, , drop = FALSE]
indices_mask <- setdiff(1:n_total, indices_remain)
xy.c_observed_mask <- xy.c_observed[indices_mask, , drop = FALSE]
xy.c_observed = xy.c_observed_remain
N = nrow(xy.c_observed)

mesh_vertices <- mesh_full$loc[ ,1:2]
nn_result <- get.knnx(data = mesh_vertices,
                      query = loc_test,
                      k = 1)
mesh_ind_loc_test <- nn_result$nn.index[, 1]

# plot
# par(mar = c(0, 0, 2, 0))
# plot(mesh_full, asp = 1, main = '')
# points(mesh_full$loc[,1:2], pch = 20, col = 'black')
# points(loc_test, pch = 20, col = 'red')
# points(mesh_full$loc[mesh_ind_loc_test,1:2], col = 'blue')
# title('Mesh Over Bei Data')
# rm(mesh_vertices, mesh_loc, nn_result)

#------------------------------- Dual mesh -------------------------------
loc_n_N = rbind(mesh_vertices, xy.c_observed)

#------------------------------- covariate ----------------------------------
X = cbind(rep(1, N), gridcov[Reduce('cbind', nearest.pixel(xy.c_observed[,1], xy.c_observed[,2],im(gridcov, x0, y0)))])
X_tilde = cbind(rep(1, n), gridcov[Reduce('cbind', nearest.pixel(mesh_vertices[,1], mesh_vertices[,2],im(gridcov, x0, y0)))])
X_test = cbind(rep(1, n_test), gridcov[Reduce('cbind', nearest.pixel(loc_test[,1], loc_test[,2],im(gridcov, x0, y0)))])


# A_tilde and A
zero_block1 = matrix(0, nrow = n, ncol = N)
zero_block2 = matrix(0, nrow = N, ncol = n)
A_tilde = as(cbind(diag(n), zero_block1), "dgCMatrix")
A = as(cbind(zero_block2, diag(N)), "dgCMatrix")

rm(zero_block1, zero_block2)
rm(x0,y0,tau_0,sampling_win,sampling_x_max,sampling_x_min,sampling_y_max,sampling_y_min,min_observed_dist,min_dist,margin,ppp_test,mesh_hole,esh_vertices)
rm(n_generated)
rm(n_hole,N_hole)
save(list = ls(all.names = TRUE), file = "./data/lgcp_data_hole.RData", envir = .GlobalEnv)

# ------------------------------- plot -----------------------------------
if (!exists("lambda_values") || !is.list(lambda_values) || is.null(lambda_values$xrange) || is.null(lambda_values$yrange)) {
  stop("Cannot automatically determine common limits from lambda_values. Please define common_xlim and common_ylim.")
} else {
  common_xlim <- range(lambda_values$xrange)
  common_ylim <- range(lambda_values$yrange)
}


par(mfrow = c(1, 3),
    oma = c(0.5, 0.5, 1.5, 0.5), 
    mar = c(0.5, 0.5, 0.5, 0.5)) 


label_cex <- 1.5 # Adjust label size
label_font <- 2   # Bold font
# y_offset_above: How much higher than the top border the text bottom should be
y_offset_above <- diff(common_ylim) * 0.05 # Adjust as needed (e.g., 0.01 to 0.05)

image(lambda_values, col = viridis(256),
      xlim = common_xlim, ylim = common_ylim, asp = 1,
      axes = FALSE, xlab = "", ylab = "", main = "")
points(DP_with_hole1$xy_c_observed, pch = 16, cex = 0.5)
points(DP_with_hole1$xy_c_unobserved, pch = 16, cex = 0.5)
contour(lambda_values, add = TRUE, col = "black")
mtext("(a)", side = 3, line = -1, at = -0.1, cex = 1.6, adj = 0)
mtext("Point pattern and log-intensity surface", side = 1, line = -0.4, cex = 1.6) 

plot(0, 0, type = 'n',
     xlim = common_xlim, ylim = common_ylim, asp = 1,
     xlab = "", ylab = "", axes = FALSE, main = "")
plot(dual_mesh_plot, lwd = 1, border="grey", add = TRUE)
points(DP_with_hole1$xy_c_observed, col = 'blue', pch = 19, cex = 0.4)
points(DP_with_hole1$xy_c_unobserved, col = 'blue', pch = 19, cex = 0.4)
points(Dualmesh_loc, col = 'grey', pch = 19, cex = 0.4)
polygon(square_boundary, border = "black", lwd = 2, col = NA)
mtext("(b)", side = 3, line = -1, at = -0.1, cex = 1.6, adj = 0)
mtext("Full case", side = 1, line = -0.4, cex = 1.6) 

plot(0, 0, type = 'n',
     xlim = common_xlim, ylim = common_ylim, asp = 1,
     xlab = "", ylab = "", axes = FALSE, main = "")
plot(dual_mesh_plot, lwd = 1, border="grey", add = TRUE)
points(xy.c_observed_remain, col = 'blue', pch = 19, cex = 0.4)
points(rbind(DP_with_hole1$xy_c_unobserved, xy.c_observed_mask), col = "green", pch = "+")
points(Dualmesh_loc, col = 'grey', pch = 19, cex = 0.4)
rect(pl.dom_hole[1,1], pl.dom_hole[1,2], pl.dom_hole[2,1], pl.dom_hole[3,2], border = 'red', lwd = 2)
polygon(square_boundary, border = "black", lwd = 2, col = NA)
mtext("(c)", side = 3, line = -1, at = -0.1, cex = 1.6, adj = 0)
mtext("Hole case", side = 1, line = -0.4, cex = 1.6) 

def.par <- par(no.readonly = TRUE)
par(mfrow = c(1, 1), oma = def.par$oma, mar = def.par$mar)
dev.off()
