| Title: | Weighted Sum Scores for Protein Network Modules |
|---|---|
| Description: | Computes Weighted Sum Score (WSS) module-level summaries from proteomic data. Protein-level values are sign-aligned to their association with core biomarkers and combined within 'STRING' network modules, weighted by network connectivity and association strength. Bundled reference modules and a fitted 'joinet' model also allow all module scores to be predicted from age, sex and a small panel of plasma biomarkers, without measuring the full proteomic panel. The method is described in Butler et al. (2026) <doi:10.64898/2026.08.14.26360394>. |
| Authors: | Robert Butler [aut, cre] (ORCID: <https://orcid.org/0000-0003-0200-8682>), WSSmod authors [cph] |
| Maintainer: | Robert Butler <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.1.0.9000 |
| Built: | 2026-11-04 22:09:07 UTC |
| Source: | https://github.com/longo-lab/wssmod |
This function calculates module scores by sign-flipping proteins based on their biomarker associations (mean_beta) and weighting by alpha centrality. This approach aligns proteins in the direction of core biomarker progression and weights by network importance and biomarker association strength.
calculate_WSS( expr_matrix, result = NULL, prebuilt = "core_AD_plasma_biomarkers", dedup_by = "mean_alpha_scaled", min_module_size = 3 )calculate_WSS( expr_matrix, result = NULL, prebuilt = "core_AD_plasma_biomarkers", dedup_by = "mean_alpha_scaled", min_module_size = 3 )
expr_matrix |
A numeric matrix with samples as rows and genes/proteins as columns, already normalized and scaled (see Details). Column names should match the 'symbol' values in the result table. Proteins used by a module must not have missing values (see Details). |
result |
A data.table containing module information with required columns:
module, symbol (gene identifiers), mean_beta (for sign-flipping),
mean_alpha_scaled (for weighting). A data.frame is converted to a
data.table; any other class is an error. If |
prebuilt |
Name of a prebuilt reference set to use when |
dedup_by |
Name of the column used to rank duplicate gene/module
assignments when a gene appears in |
min_module_size |
Minimum number of genes a module must retain
(after deduplication) to be included in the output. Defaults to |
For each module, proteins are sign-flipped based on sign(mean_beta) to align all proteins in the direction of disease progression. The signed values are then weighted by mean_alpha_scaled (network centrality + association strength) and averaged to produce a module score.
Higher module scores indicate greater module activity in the direction of disease progression.
Input scale. The function does no normalization or scaling of
expr_matrix; supply values that are already normalized and scaled. Each
module score is a weighted average of sign-aligned protein values, so the
scores inherit the scale of the input, whether that is a rank-based inverse
normal transformed (INT) scale, z-scaled log2 ratios, or another choice
appropriate to the platform. The bundled reference set was built from
SomaScan data on an INT scale. Scores computed on differently normalized or
scaled input are not directly comparable with each other, and
predict_WSS() predicts scores on the INT-based scale of the bundled
reference.
Missing values. Modules are scored from the proteins that are present in
expr_matrix (see the return value for modules with no proteins present),
but missing values (NA) in a protein that a module uses are not supported:
the function stops with an error that names the affected proteins. Impute
the values, or drop the affected proteins or samples, before scoring.
Missing values in proteins that no module uses are ignored.
A list containing:
scores |
Matrix of Weighted Sum Scores (samples x modules) |
summary_stats |
data.table with summary statistics for each module score |
module_sd |
Named vector of standard deviations for each module |
module_proteins |
List of protein names in each module |
A module with none of its proteins in expr_matrix cannot be scored. It
triggers a warning, has all-NA scores and a module_sd of 0, and is left
out of summary_stats and module_proteins.
list_prebuilt_wss(), load_prebuilt_wss(), load_prebuilt_terms()
expr_matrix <- matrix( c(1, 2, 3, 4, 5, 6, 7, 8), nrow = 2, dimnames = list(c("sample1", "sample2"), c("geneA", "geneB", "geneC", "geneD")) ) cluster_result <- data.table::data.table( module = c("mod1", "mod1", "mod1", "mod2"), symbol = c("geneA", "geneB", "geneC", "geneD"), mean_beta = c(1, -1, 1, 1), mean_alpha_scaled = c(1, 1, 2, 1) ) # Calculate Weighted Sum Scores (min_module_size = 1 to keep this toy example) module_results <- calculate_WSS(expr_matrix, cluster_result, min_module_size = 1) # Access score matrix scores <- module_results$scores # View summary statistics print(module_results$summary_stats) # Check standard deviations print(module_results$module_sd) # With no `result`, the default bundled reference set is used. The # simulated example matrix has columns for all of its modules. default_results <- calculate_WSS(wss_example_expression) dim(default_results$scores)expr_matrix <- matrix( c(1, 2, 3, 4, 5, 6, 7, 8), nrow = 2, dimnames = list(c("sample1", "sample2"), c("geneA", "geneB", "geneC", "geneD")) ) cluster_result <- data.table::data.table( module = c("mod1", "mod1", "mod1", "mod2"), symbol = c("geneA", "geneB", "geneC", "geneD"), mean_beta = c(1, -1, 1, 1), mean_alpha_scaled = c(1, 1, 2, 1) ) # Calculate Weighted Sum Scores (min_module_size = 1 to keep this toy example) module_results <- calculate_WSS(expr_matrix, cluster_result, min_module_size = 1) # Access score matrix scores <- module_results$scores # View summary statistics print(module_results$summary_stats) # Check standard deviations print(module_results$module_sd) # With no `result`, the default bundled reference set is used. The # simulated example matrix has columns for all of its modules. default_results <- calculate_WSS(wss_example_expression) dim(default_results$scores)
List Available Prebuilt WSS Reference Sets
list_prebuilt_wss()list_prebuilt_wss()
A character vector of prebuilt reference set names usable as the
prebuilt argument of calculate_WSS() and load_prebuilt_wss().
list_prebuilt_wss()list_prebuilt_wss()
Some prebuilt reference sets ship a baseline biomarker reference
distribution used by normalize_wss_biomarkers() (method = "project")
to rank-normalize new raw biomarker values without needing a sizeable
cohort of your own. Each biomarker's reference values are drawn from the
real baseline cohort, but independently randomly shuffled so that no
two values across different biomarkers can be attributed to the same
original subject. This preserves each biomarker's marginal distribution
exactly (every value, tie, and extreme is real) while destroying the
joint/multivariate fingerprint that carries re-identification risk.
load_prebuilt_biomarker_reference(prebuilt = "core_AD_plasma_biomarkers")load_prebuilt_biomarker_reference(prebuilt = "core_AD_plasma_biomarkers")
prebuilt |
Name of a prebuilt reference set. See
|
Because of this, the returned reference has no valid joint structure — inter-biomarker correlations are deliberately destroyed. Only use it for independent per-biomarker operations (rank/quantile lookups), never for anything requiring multivariate relationships (e.g. correlation or joint modeling).
A data.table with columns biomarker and value (long format,
one row per reference observation), or NULL if the given reference set
has no associated biomarker reference.
normalize_wss_biomarkers(), project_rank_norm()
ref <- load_prebuilt_biomarker_reference() table(ref$biomarker)ref <- load_prebuilt_biomarker_reference() table(ref$biomarker)
Some prebuilt reference sets ship a companion table of human-readable term labels for each module, summarized from the underlying pathway enrichment used to build the module.
load_prebuilt_terms(prebuilt = "core_AD_plasma_biomarkers")load_prebuilt_terms(prebuilt = "core_AD_plasma_biomarkers")
prebuilt |
Name of a prebuilt reference set. See
|
A data.table of module term labels, or NULL if the given
reference set has no associated terms file.
head(load_prebuilt_terms())head(load_prebuilt_terms())
Reads one of the module weighting tables shipped with WSSmod. The raw
table may assign the same protein to more than one module (e.g. once per
biomarker it was associated with); calculate_WSS() deduplicates and
filters this table before use via dedup_by and min_module_size.
load_prebuilt_wss(prebuilt = "core_AD_plasma_biomarkers")load_prebuilt_wss(prebuilt = "core_AD_plasma_biomarkers")
prebuilt |
Name of a prebuilt reference set. See
|
A data.table with (at least) columns module, symbol,
mean_beta, and mean_alpha_scaled, suitable for use as the result
argument of calculate_WSS().
calculate_WSS(), list_prebuilt_wss(), load_prebuilt_terms()
ref <- load_prebuilt_wss() head(ref[, c("module", "symbol", "mean_beta", "mean_alpha_scaled")])ref <- load_prebuilt_wss() head(ref[, c("module", "symbol", "mean_beta", "mean_alpha_scaled")])
Some prebuilt reference sets ship a fitted joinet model (a two-layer
elastic net) that predicts all of that reference set's module scores from
a small set of covariates, without needing to measure the full proteomic
panel. See predict_WSS() to predict from this model directly.
load_prebuilt_wss_model(prebuilt = "core_AD_plasma_biomarkers")load_prebuilt_wss_model(prebuilt = "core_AD_plasma_biomarkers")
prebuilt |
Name of a prebuilt reference set. See
|
A list with components model (the fitted joinet object),
outcomes (the module names it predicts), x_cols (the required
predictor columns, in order), and variant; or NULL if the given
reference set has no associated prediction model.
predict_WSS(), list_prebuilt_wss()
model_info <- load_prebuilt_wss_model() model_info$variant model_info$x_cols head(model_info$outcomes)model_info <- load_prebuilt_wss_model() model_info$variant model_info$x_cols head(model_info$outcomes)
Builds the rank-based inverse-normal-transformed biomarker columns
predict_WSS() requires, from raw biomarker values, using one of two
methods. Output columns keep the same names as the input columns (e.g.
PlasmaPTau181 stays PlasmaPTau181) – predict_WSS() reads whatever
column names its underlying model actually expects.
normalize_wss_biomarkers( raw_biomarkers, prebuilt = "core_AD_plasma_biomarkers", method = c("project", "self") )normalize_wss_biomarkers( raw_biomarkers, prebuilt = "core_AD_plasma_biomarkers", method = c("project", "self") )
raw_biomarkers |
A data.frame or matrix, one row per sample, with
columns named by the raw (unsuffixed) biomarker names (e.g.
|
prebuilt |
Name of a prebuilt reference set to use when
|
method |
Normalization method:
|
A data.frame with one normalized column per input biomarker
column (same names as raw_biomarkers), row names preserved. Combine
with Age/Gender columns and pass to predict_WSS().
predict_WSS(), project_rank_norm(),
load_prebuilt_biomarker_reference()
raw_biomarkers <- data.frame(PlasmaPTau181 = 1.5, PlasmaNfL = 20) normalize_wss_biomarkers(raw_biomarkers)raw_biomarkers <- data.frame(PlasmaPTau181 = 1.5, PlasmaNfL = 20) normalize_wss_biomarkers(raw_biomarkers)
Predicts module scores for a prebuilt reference set's joinet model (a
two-layer elastic net stack) without needing to measure the full
proteomic panel. For "core_AD_plasma_biomarkers", this predicts all 75
module scores from Age, Gender, and the 8 core plasma biomarkers used in
the original analysis.
predict_WSS(newdata, prebuilt = "core_AD_plasma_biomarkers", type = "response")predict_WSS(newdata, prebuilt = "core_AD_plasma_biomarkers", type = "response")
newdata |
A data.frame or matrix with one row per sample and (at
least) the columns required by the model; see The biomarker columns must already be rank-based inverse-normal
transformed before calling this function – see
|
prebuilt |
Name of a prebuilt reference set. See
|
type |
Prediction type passed to |
A list with components base (first-layer-only predictions) and
meta (final stacked predictions), each a matrix with one row per
sample (row names taken from newdata, if present) and one column per
module (named by the model's outcomes).
normalize_wss_biomarkers(), load_prebuilt_wss_model(),
calculate_WSS()
if (requireNamespace("glmnet", quietly = TRUE) && requireNamespace("joinet", quietly = TRUE)) { # Simulated raw biomarkers; works for a single patient too raw_biomarkers <- wss_example_biomarkers[, -(1:2)] normalized <- normalize_wss_biomarkers(raw_biomarkers) newdata <- cbind( Age = wss_example_biomarkers$Age, Gender = wss_example_biomarkers$Gender, normalized ) pred <- predict_WSS(newdata) pred$meta[1:3, 1:4] }if (requireNamespace("glmnet", quietly = TRUE) && requireNamespace("joinet", quietly = TRUE)) { # Simulated raw biomarkers; works for a single patient too raw_biomarkers <- wss_example_biomarkers[, -(1:2)] normalized <- normalize_wss_biomarkers(raw_biomarkers) newdata <- cbind( Age = wss_example_biomarkers$Age, Gender = wss_example_biomarkers$Gender, normalized ) pred <- predict_WSS(newdata) pred$meta[1:3, 1:4] }
Projects new_vals onto the rank-based inverse-normal transform defined
by train_vals, without ever refitting or observing new_vals when
determining the transform. Each new value is treated as a single
insertion into the frozen, sorted train_vals reference: its rank is the
count of reference values at or below it (ties in train_vals share the
same rank), and that rank is converted to a normal quantile using the
same Blom-type constant (k = 0.375) as RNOmni::RankNorm().
project_rank_norm(train_vals, new_vals, k = 0.375)project_rank_norm(train_vals, new_vals, k = 0.375)
train_vals |
Numeric vector, the frozen reference distribution
(e.g. a baseline cohort's biomarker values). Must not contain |
new_vals |
Numeric vector of new values to project onto
|
k |
Blom-type constant, passed through to match
|
This is useful for scoring new samples (including a single new sample) against a fixed reference cohort without leaking information from the new samples into the reference's distribution – e.g. avoiding the train/test leakage that results from rank-normalizing a pooled reference+new-sample dataset together.
Note this does not reproduce RNOmni::RankNorm(train_vals)
bit-for-bit when new_vals happens to equal train_vals: it always
treats each new value as an additional observation inserted into the
n-sample reference (using n + 1 in the denominator), rather than as
one of the original n samples. The two are close but not identical.
A numeric vector the same length as new_vals, giving each
value's projected normal quantile.
train_vals <- rnorm(200) project_rank_norm(train_vals, new_vals = c(-1, 0, 1))train_vals <- rnorm(200) project_rank_norm(train_vals, new_vals = c(-1, 0, 1))
A small, fully simulated table of raw plasma biomarker values for trying
out normalize_wss_biomarkers() and predict_WSS(). Biomarkers are drawn
from log-normal distributions at plausible scales. The data are random
draws and contain no participant data; they carry no biological meaning
and are for demonstration only.
wss_example_biomarkerswss_example_biomarkers
A data.frame with 20 rows (named patient01 to patient20) and
10 columns:
Age in years.
1 = male, 0 = not male.
Raw (un-normalized) plasma biomarker values.
Simulated; see data-raw/simulate_examples.R in the package
source.
normalize_wss_biomarkers(), predict_WSS(),
wss_example_expression
head(wss_example_biomarkers)head(wss_example_biomarkers)
A small, fully simulated samples-by-proteins matrix for trying out
calculate_WSS(). Its columns are the 887 proteins (gene symbols) that
survive the default deduplication and module-size filter of the bundled
"core_AD_plasma_biomarkers" reference set, so
calculate_WSS(wss_example_expression) scores all 75 modules without
warnings. Values are on a z-score-like scale, as expected for normalized
input.
wss_example_expressionwss_example_expression
A numeric matrix with 50 rows (samples, named sample01 to
sample50) and 887 columns (proteins, named by gene symbol).
Each module was given a latent per-sample factor, and its proteins load on
that factor in the direction of their mean_beta, plus independent noise.
The data are random draws and contain no participant data; they carry no
biological meaning and are for demonstration only.
Simulated; see data-raw/simulate_examples.R in the package
source.
calculate_WSS(), wss_example_biomarkers
dim(wss_example_expression) res <- calculate_WSS(wss_example_expression) head(res$scores[, 1:3])dim(wss_example_expression) res <- calculate_WSS(wss_example_expression) head(res$scores[, 1:3])