Skip to content

Commit a2aa4e2

Browse files
committed
skip gwas in focal mode if colocboost errors
1 parent 51ba8e8 commit a2aa4e2

1 file changed

Lines changed: 69 additions & 17 deletions

File tree

R/colocboost_pipeline.R

Lines changed: 69 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,35 @@ colocboost_analysis_pipeline <- function(region_data,
470470
sumstats <- LD_mat <- dict_sumstatLD <- NULL
471471
}
472472

473+
# Helper: validate a single GWAS study data.frame and its LD matrix
474+
is_valid_sumstat_entry <- function(df, ld_matrix) {
475+
if (is.null(df) || nrow(df) == 0) return(FALSE)
476+
if (!all(c("z", "n", "variant") %in% colnames(df))) return(FALSE)
477+
n_vals <- suppressWarnings(as.numeric(unique(df$n)))
478+
if (length(n_vals) == 0 || is.na(n_vals[1]) || !is.finite(n_vals[1]) || n_vals[1] < 3) return(FALSE)
479+
if (all(is.na(df$z))) return(FALSE)
480+
if (is.null(ld_matrix)) return(FALSE)
481+
if (!is.matrix(ld_matrix)) return(FALSE)
482+
if (any(!is.finite(ld_matrix))) return(FALSE)
483+
# Ensure at least 1 overlapping variant with LD matrix dimnames
484+
ld_vars <- intersect(rownames(ld_matrix), colnames(ld_matrix))
485+
if (length(ld_vars) == 0) return(FALSE)
486+
if (length(intersect(as.character(df$variant), as.character(ld_vars))) == 0) return(FALSE)
487+
TRUE
488+
}
489+
490+
# Helper: filter joint structures (sumstats list and dict_sumstatLD) to only valid entries
491+
filter_valid_sumstats <- function(sumstats, LD_mat, dict_sumstatLD) {
492+
if (is.null(sumstats) || is.null(dict_sumstatLD) || is.null(LD_mat)) return(list(sumstats = NULL, dict = NULL))
493+
keep <- vector("logical", length(sumstats))
494+
for (i in seq_along(sumstats)) {
495+
ld_idx <- dict_sumstatLD[i, 2]
496+
ld_matrix <- if (!is.na(ld_idx)) LD_mat[[ld_idx]] else NULL
497+
keep[i] <- is_valid_sumstat_entry(sumstats[[i]], ld_matrix)
498+
}
499+
if (!any(keep)) return(list(sumstats = NULL, dict = NULL))
500+
list(sumstats = sumstats[keep], dict = matrix(dict_sumstatLD[keep, , drop = FALSE], ncol = 2))
501+
}
473502

474503
####### ========= streamline three types of analyses ======== ########
475504
if (is.null(X) & is.null(sumstats)) {
@@ -500,32 +529,55 @@ colocboost_analysis_pipeline <- function(region_data,
500529
if (joint_gwas & !is.null(sumstats)) {
501530
message(paste("====== Performing non-focaled version GWAS-xQTL ColocBoost on", length(Y), "contexts and", length(sumstats), "GWAS. ====="))
502531
t21 <- Sys.time()
503-
traits <- c(names(Y), names(sumstats))
504-
res_gwas <- colocboost(
505-
X = X, Y = Y, sumstat = sumstats, LD = LD_mat,
506-
dict_YX = dict_YX, dict_sumstatLD = dict_sumstatLD,
507-
outcome_names = traits, focal_outcome_idx = NULL,
508-
output_level = 2, ...
509-
)
510-
t22 <- Sys.time()
511-
analysis_results$joint_gwas <- res_gwas
512-
analysis_results$computing_time$Analysis$joint_gwas <- t22 - t21
532+
# Filter invalid GWAS before calling colocboost
533+
filtered <- filter_valid_sumstats(sumstats, LD_mat, dict_sumstatLD)
534+
if (is.null(filtered$sumstats)) {
535+
message("All GWAS studies failed validation; skipping joint GWAS analysis for this region.")
536+
} else {
537+
traits <- c(names(Y), names(filtered$sumstats))
538+
res_gwas <- colocboost(
539+
X = X, Y = Y, sumstat = filtered$sumstats, LD = LD_mat,
540+
dict_YX = dict_YX, dict_sumstatLD = filtered$dict,
541+
outcome_names = traits, focal_outcome_idx = NULL,
542+
output_level = 2, ...
543+
)
544+
t22 <- Sys.time()
545+
analysis_results$joint_gwas <- res_gwas
546+
analysis_results$computing_time$Analysis$joint_gwas <- t22 - t21
547+
}
513548
}
514549
# - run focaled version of ColocBoost for each GWAS
515550
if (separate_gwas & !is.null(sumstats)) {
516551
t31 <- Sys.time()
517552
res_gwas_separate <- analysis_results$separate_gwas
518553
for (i_gwas in 1:nrow(dict_sumstatLD)) {
519554
current_study <- names(sumstats)[i_gwas]
520-
message(paste("====== Performing focaled version GWAS-xQTL ColocBoost on", length(Y), "contexts and ", current_study, "GWAS. ====="))
521555
dict <- dict_sumstatLD[i_gwas, ]
556+
# Validate this study before calling colocboost
557+
ld_idx <- dict[2]
558+
ld_matrix <- if (!is.na(ld_idx)) LD_mat[[ld_idx]] else NULL
559+
valid <- is_valid_sumstat_entry(sumstats[[dict[1]]], ld_matrix)
560+
if (!isTRUE(valid)) {
561+
message(paste("Skipping", current_study, "due to invalid N/z/LD."))
562+
next
563+
}
564+
message(paste("====== Performing focaled version GWAS-xQTL ColocBoost on", length(Y), "contexts and ", current_study, "GWAS. ====="))
522565
traits <- c(names(Y), current_study)
523-
res_gwas_separate[[current_study]] <- colocboost(
524-
X = X, Y = Y, sumstat = sumstats[dict[1]],
525-
LD = LD_mat[dict[2]], dict_YX = dict_YX,
526-
outcome_names = traits, focal_outcome_idx = length(traits),
527-
output_level = 2, ...
528-
)
566+
567+
# Try to run colocboost with error handling
568+
tryCatch({
569+
res_gwas_separate[[current_study]] <- colocboost(
570+
X = X, Y = Y, sumstat = sumstats[dict[1]],
571+
LD = LD_mat[dict[2]], dict_YX = dict_YX,
572+
outcome_names = traits, focal_outcome_idx = length(traits),
573+
output_level = 2, ...
574+
)
575+
}, error = function(e) {
576+
message(paste("Error in colocboost analysis for", current_study, ":"))
577+
message(paste("Error message:", e$message))
578+
message(paste("Continuing with next GWAS..."))
579+
res_gwas_separate[[current_study]] <<- NULL
580+
})
529581
}
530582
t32 <- Sys.time()
531583
analysis_results$separate_gwas <- res_gwas_separate

0 commit comments

Comments
 (0)