Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Package: colocboost
Type: Package
Date: 2025-11-22
Date: 2026-06-06
Title: Multi-Context Colocalization Analysis for QTL and GWAS Studies
Version: 1.0.7
Version: 1.0.8
Authors@R: c(
person(given = "Xuewei", family = "Cao", email = "xc2270@cumc.columbia.edu", role = c("cre", "aut", "cph")),
person(given = "Haochen", family = "Sun", email = "hs3393@cumc.columbia.edu", role = c("aut", "cph")),
Expand Down
5 changes: 2 additions & 3 deletions R/colocboost.R
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ colocboost <- function(X = NULL, Y = NULL, # individual data
#' \item{sumstat}{Processed list of summary statistics data.frames}
#' \item{LD}{Processed list of LD matrices}
#' \item{X_ref}{Processed list of reference genotype matrices}
#' \item{ref_label}{Style of reference matrics}
#' \item{ref_label}{Style of reference matrices}
#' \item{sumstatLD_dict}{Dictionary mapping sumstat to LD}
#' \item{keep_variable_sumstat}{List of variant names for each sumstat}
#' \item{Z}{List of z-scores for each outcome}
Expand Down Expand Up @@ -514,7 +514,7 @@ colocboost_validate_input_data <- function(X = NULL, Y = NULL,
})
keep_variable_individual <- lapply(X, colnames)
if (!is.list(X) & !is.list(Y)) {
warning("Error: Input X and Y must be the list containing genotype matrics and all phenotype vectors!")
warning("Error: Input X and Y must be the list containing genotype matrices and all phenotype vectors!")
return(NULL)
} else {
if (length(X) == 1) {
Expand Down Expand Up @@ -968,4 +968,3 @@ colocboost_validate_input_data <- function(X = NULL, Y = NULL,
npc_outcome_cutoff = npc_outcome_cutoff_updated
))
}

11 changes: 4 additions & 7 deletions R/colocboost_output.R
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ get_robust_colocalization <- function(cb_output,
for (i in 1:length(cos_details$cos$cos_index)) {
cos_npc_config <- cos_details$cos_outcomes_npc[[i]]
npc_outcome <- cos_npc_config$npc_outcome
pos_pass <- which(npc_outcome >= npc_outcome_cutoff)
pos_pass <- which(npc_outcome >= npc_outcome_cutoff & npc_outcome > 0)
if (!is.null(pvalue_cutoff)) {
cos_tmp <- cos_details$cos$cos_index[[i]]
cos_trait <- cos_details$cos_outcomes$outcome_index[[i]]
Expand Down Expand Up @@ -517,8 +517,7 @@ get_robust_ucos <- function(cb_output,
}

if (npc_outcome_cutoff == 0 && is.null(pvalue_cutoff)) {
message("All possible uncolocalized events are reported regardless of their relative evidence (npc_outcome_cutoff = 0).")
return(cb_output)
message("All possible uncolocalized events with positive relative evidence are reported (npc_outcome_cutoff = 0).")
} else {
if (is.null(pvalue_cutoff)) {
message(paste0(
Expand Down Expand Up @@ -580,7 +579,7 @@ get_robust_ucos <- function(cb_output,
ucolocset_names <- ucos_min_npc_outcome <- c()
for (i in 1:length(ucos_details$ucos$ucos_index)) {
npc_outcome <- ucos_details$ucos_outcomes_npc$npc_outcome[i]
pos_pass <- which(npc_outcome >= npc_outcome_cutoff)
pos_pass <- which(npc_outcome >= npc_outcome_cutoff & npc_outcome > 0)
if (!is.null(pvalue_cutoff)) {
ucos_tmp <- ucos_details$ucos$ucos_index[[i]]
ucos_trait <- ucos_details$ucos_outcomes$outcome_index[[i]]
Expand All @@ -592,8 +591,6 @@ get_robust_ucos <- function(cb_output,
pos_pass_pvalue <- which(minPV <= pvalue_cutoff)
if (length(pos_pass_pvalue) == 0) {
pos_pass <- NULL
} else {
pos_pass <- 1
}
}
if (length(pos_pass) == 0) {
Expand Down Expand Up @@ -1472,4 +1469,4 @@ merge_ucos_details <- function(ucos_details, ucos_from_cos) {
),
"ucos_outcomes_npc" = rbind(ucos_details$ucos_outcomes_npc, ucos_from_cos$ucos_outcomes_npc)
)
}
}
28 changes: 22 additions & 6 deletions cran-comments.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,26 @@
## colocboost 1.0.8 release comments

## New release comments
This is an update to colocboost 1.0.7.

* This release includes three major improvements:
- Enhanced main function by adding post-filtering step.
- Enhanced plot function with flexible highlighting options.
- Optimized performance and computational efficiency.
This release includes:

* Added X_ref support as a memory-efficient alternative to precomputed LD matrices for summary-statistics workflows.
* Added and refined robust post-filtering for colocalization and trait-specific uncolocalized events.
* Improved computational efficiency for repeated matrix products in reference-panel workflows.
* Improved plotting robustness for extreme association signals and coefficient or z-score displays.
* Updated documentation and vignettes, including the bioinformatics pipeline vignette.

## R CMD check results

There is one NOTE about installed package size:

* checking installed package size ... NOTE
installed size is 5.0 MB
sub-directories of 1Mb or more:
data 2.0 MB
doc 1.9 MB

This NOTE is expected. The installed size is mainly due to reduced example datasets and rendered vignettes with figures. These files are kept to make the tutorials reproducible and self-contained for multi-trait colocalization workflows. No external data are downloaded during examples or vignette rendering.

## Previous comments

Expand All @@ -15,4 +31,4 @@
- Fixed reset users' options issues
- Added proper COPYRIGHT HOLDER and ORGANIZATION to LICENSE
- Added explanation of acronyms used in this package to inst/WORDLIST
* The examples and vignettes use small datasets to avoid long check times
* The examples and vignettes use small datasets to avoid long check times
11 changes: 10 additions & 1 deletion inst/WORDLIST
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ HyPrColoc # Hypothesis Prioritization in multi-trait Colocalization method
SuSiE # Sum of Single Effects regression model

# Statistical and Genetic Terms
bim # PLINK BIM variant information file
eQTL # Expression Quantitative Trait Loci
GWAS # Genome-Wide Association Study
INDELs # Insertions and Deletions
Expand All @@ -31,11 +32,14 @@ GTEx # Genotype-Tissue Expression project
Micromamba # Lightweight Conda implementation
Nealelab # Lab developing genetics GWAS summary statistics
PLINK # Whole genome association analysis toolset
RAISS # Summary-statistics imputation method
tabix # Tool for indexing genomic data
UKBB # UK Biobank dataset
YAML # Human-readable configuration file format
medRxiv # A preprint resource
pixi # An environment manager
conda # Package and environment management system
xz # Compression format

# Researcher Names
Jager # Philip L. de Jager
Expand All @@ -48,18 +52,23 @@ et # and more
al # and more

# Technical Terms
changelog # Release change log
cis # Referring to nearby location of a regulatory element
chrom # Chromosome
decayrate # Decay rate, an input parameter in our package
doi # Digital Object Identifier
func # Function abbreviation used in parameter names
grey # One color name in R
iteratively # Performed through iterations
loglik # Log-likelihood abbreviation used in parameter names
lfsr # Local False Sign Rate
lth # Lower threshold
modularity # Property of network structure
omics # Collective biological data fields
phenotypes # Observable traits
pos # Position in genome
precomputed # Computed in advance
precomputes # Computes in advance
probabilistically # Based on probability theory
qc # Quality Control
rcond # Reciprocal condition number
Expand Down Expand Up @@ -89,4 +98,4 @@ npc # Normalization probability of colocalization in our proposed Co
Pre # Before
pre # Before
jk # Index used in ColocBoost
nd # Second
nd # Second
2 changes: 1 addition & 1 deletion man/colocboost_validate_input_data.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

116 changes: 115 additions & 1 deletion tests/testthat/test_inference.R
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,38 @@ generate_ucos_test_data <- function(n = 500, p = 60, L = 3, seed = 42, output_le
return(result)
}

generate_cos_test_result <- function(n = 250, p = 30, L = 3, seed = 20260606) {
set.seed(seed)

sigma <- 0.9^abs(outer(seq_len(p), seq_len(p), "-"))
X <- MASS::mvrnorm(n, rep(0, p), sigma)
colnames(X) <- paste0("SNP", seq_len(p))

true_beta <- matrix(0, p, L)
true_beta[8, 1] <- 1.2
true_beta[8, 2] <- 1.1
true_beta[22, 3] <- 1.2

Y <- matrix(0, n, L)
for (l in seq_len(L)) {
Y[, l] <- X %*% true_beta[, l] + rnorm(n, 0, 0.6)
}

suppressWarnings({
result <- colocboost(
X = replicate(L, X, simplify = FALSE),
Y = lapply(seq_len(L), function(l) Y[, l]),
M = 80,
output_level = 3,
cos_npc_cutoff = 0,
npc_outcome_cutoff = 0,
pvalue_cutoff = NULL
)
})

return(result)
}



# Test for get_strong_colocalization
Expand All @@ -125,6 +157,61 @@ test_that("get_robust_colocalization filters results correctly", {
expect_error(suppressWarnings(get_robust_colocalization(cb_res, pvalue_cutoff = 0.05)), NA)
})

test_that("get_robust_colocalization handles validation and early return branches", {

cb_res <- generate_cos_test_result()
expect_false(is.null(cb_res$cos_details))

expect_error(
get_robust_colocalization("not_a_colocboost_object"),
"colocboost object"
)

no_cos <- cb_res
no_cos$cos_details <- NULL
expect_message(
no_cos_result <- get_robust_colocalization(no_cos),
"No colocalization results"
)
expect_null(no_cos_result$cos_details)

expect_warning(
bad_pvalue_result <- get_robust_colocalization(cb_res, pvalue_cutoff = 1.5),
"pvalue cutoff"
)
expect_equal(bad_pvalue_result, cb_res)

expect_message(
all_events_result <- get_robust_colocalization(
cb_res,
cos_npc_cutoff = 0,
npc_outcome_cutoff = 0
),
"All possible colocalization events"
)
expect_equal(all_events_result, cb_res)
})

test_that("get_robust_colocalization removes CoS with zero npc_outcome", {

cb_res <- generate_cos_test_result()
expect_false(is.null(cb_res$cos_details))

cb_res$cos_details$cos_outcomes_npc[[1]]$npc_outcome <- 0

expect_message(
filtered <- get_robust_colocalization(
cb_res,
cos_npc_cutoff = 0.2,
npc_outcome_cutoff = 0
),
"Extracting colocalization results"
)

expect_s3_class(filtered, "colocboost")
expect_null(filtered$cos_details)
})

# Test for get_hierarchical_clusters
test_that("get_hierarchical_clusters functions correctly", {
# Test case 1: Simple 2x2 correlation matrix with high correlation
Expand Down Expand Up @@ -598,7 +685,7 @@ test_that("get_robust_ucos handles npc_outcome_cutoff = 0 correctly", {
# With npc_outcome_cutoff = 0 and no pvalue_cutoff, should return unchanged
expect_message(
result <- get_robust_ucos(cb_res, npc_outcome_cutoff = 0),
"All possible uncolocalized events are reported"
"positive relative evidence"
)

# Should be essentially unchanged
Expand All @@ -608,6 +695,33 @@ test_that("get_robust_ucos handles npc_outcome_cutoff = 0 correctly", {
)
})

test_that("get_robust_ucos removes zero npc_outcome even with zero cutoff", {

# Generate test data
cb_res <- generate_ucos_test_data(output_level = 2)

# Skip if no ucos were detected
skip_if(is.null(cb_res$ucos_details), "No ucos detected in test data")

n_ucos_original <- length(cb_res$ucos_details$ucos$ucos_index)
cb_res$ucos_details$ucos_outcomes_npc$npc_outcome[1] <- 0

expect_message(
result <- get_robust_ucos(cb_res, npc_outcome_cutoff = 0),
"positive relative evidence"
)

if (n_ucos_original == 1) {
expect_null(result$ucos_details)
} else {
expect_equal(
length(result$ucos_details$ucos$ucos_index),
n_ucos_original - 1
)
expect_false(any(result$ucos_details$ucos_outcomes_npc$npc_outcome == 0))
}
})

test_that("get_robust_ucos handles missing ucos_details", {

# Generate test data
Expand Down
Loading