Abstract
glycoTraitR provides a streamlined workflow for analyzing glycan heterogeneity in glycoproteomics GPSM data generated by pGlyco3 or Glyco-Decipher. The package summarizes glycan structures into biologically interpretable traits, enabling downstream statistical analysis and visualization.
glycoTraitR provides a streamlined workflow for extracting, summarizing, and analyzing glycan structural traits from glycoproteomics GPSM data generated by pGlyco3 or Glyco-Decipher. Rather than focusing on individual glycoforms, glycoTraitR summarizes glycan structures into biologically interpretable composition- and structure-based traits at the site or protein level.
In this quick start guide, we demonstrate how to:
The glycoTraitR package can be installed using BiocManager.
if (!require("BiocManager", quietly = TRUE)) {
install.packages("BiocManager")
}
BiocManager::install("glycoTraitR")After installation, we load the package into the current R session. All functions used in the following examples are provided by glycoTraitR.
This section demonstrates a typical glycoTraitR workflow using GPSM data generated by pGlyco3. Equivalent import code for Glyco-Decipher results is also provided.
For reproducibility, this vignette uses a toy dataset bundled with glycoTraitR. The commented code below illustrates how to download and import the corresponding full public datasets from Zenodo.
# Option 1: Download and import the pGlyco3 result
# pglyco_url <- paste0(
# "https://zenodo.org/records/21386154/files/",
# "pGlycoDB-GP-FDR-Pro-Quant-Site.txt?download=1"
# )
# download.file(
# pglyco_url,
# destfile = "pGlyco3_GPSM.txt",
# mode = "wb"
# )
# gpsm <- read_pGlyco3_gpsm("pGlyco3_GPSM.txt")
# Option 2: Download and import the Glyco-Decipher result
# decipher_url <- paste0(
# "https://zenodo.org/records/21386154/files/",
# "decipher_result.zip?download=1"
# )
# download.file(
# decipher_url,
# destfile = "decipher_result.zip",
# mode = "wb"
# )
# unzip("decipher_result.zip")
# gpsm <- read_decipher_gpsm("decipher_result")
# Download the sample metadata used by both examples
# meta_url <- paste0(
# "https://zenodo.org/records/21386154/files/",
# "meta_mcp_2022_100433.rds?download=1"
# )
# download.file(
# meta_url,
# destfile = "meta_example.rds",
# mode = "wb"
# )
# meta <- readRDS("meta_example.rds")
# Load the bundled pGlyco3 toy dataset and sample metadata
gpsm <- readRDS(system.file("extdata", "gpsm_toyexample.rds", package = "glycoTraitR"))
meta <- readRDS(system.file("extdata", "meta_toyexample.rds", package = "glycoTraitR"))
head(gpsm)## # A tibble: 6 × 5
## Protein Peptide GlycanStructure File Count
## <chr> <chr> <chr> <chr> <int>
## 1 1OKO GYYJQSEGGSHTIQR (N(N(H(N)(H(N))(H(N(F)))))) KS_A… 1
## 2 5NTD GNVISSHGNPILLJSSIPEDPSIK (N(N(H(H(H))(H(H))))) KS_A… 1
## 3 A1AG1|A1AG2 NEEYJK (N(N(H(H(N(F)(H(A))))(H(N(H(… KS_A… 5
## 4 A1AG1|A1AG2 NEEYJK (N(N(H(H(N(F)(H(A))))(H(N(H(… KS_A… 1
## 5 A1AG1|A1AG2 NEEYJK (N(N(H(H(N(F)(H(A))))(H(N(H(… KS_A… 1
## 6 A1AG1|A1AG2 NEEYJK (N(N(H(H(N(F)(H(A))))(H(N(H(… KS_A… 1
head(meta)## # A tibble: 6 × 22
## Diagnosis `Sample number` `Tissue weight (mg)` `Age at baseline`
## <fct> <dbl> <dbl> <dbl>
## 1 Asymptomatic 1 62 77.1
## 2 Normal 110 72 70.8
## 3 Normal 118 74 75.7
## 4 Normal 12 57 80.8
## 5 Normal 125 52 89.2
## 6 Normal 127 24 85.2
## # ℹ 18 more variables: `Age at death` <dbl>, `APOE gene` <chr>, Braak <dbl>,
## # CERAD <dbl>, `Global Cog Func` <chr>, Reagan <dbl>, arteriol_scler <chr>,
## # ci_num2_gct <dbl>, ci_num2_mct <dbl>, cvda_4gp2 <chr>, dlbdx <dbl>,
## # Sex <chr>, hspath_any <dbl>, Race <chr>, tdp_cs_6reg <chr>,
## # tdp_stage4 <chr>, PMI <dbl>, File <chr>
The gpsm object contains glycopeptide-spectrum matches,
including glycan structures encoded in pGlyco3 format.
The meta object provides sample-level annotations that will
later be used to define experimental groups.
After importing the GPSM data, we use
analyze_hscore_changes() to perform the main analysis. This
wrapper function parses the identified glycan structures, extracts
glycan traits, computes sample-level heterogeneity scores, and tests for
differences between experimental groups.
By default, heterogeneity is evaluated at both the glycosylation-site
and protein levels. In this example, samples labeled as Normal
and Symptomatic are compared according to the
Diagnosis column in the metadata. Because the bundled toy
dataset was generated by pGlyco3, we set from = "pGlyco3".
For data imported with read_decipher_gpsm(), use
from = "decipher" instead.
set.seed(123)
res <- analyze_hscore_changes(
gpsm = gpsm,
from = "pGlyco3",
motifs = NULL,
meta = meta,
group_col = "Diagnosis",
group_levels = c("Normal", "Symptomatic"),
B = 1000,
min_samples = 3
)## Compute heterogeneity scores at each site and protein
## Test heterogeneity change at site
## Test heterogeneity change at protein
The gpsm argument supplies the imported GPSM table,
while from specifies the search-engine format. The
meta table links sample identifiers to their corresponding
experimental groups. The B argument controls the number of
label permutations used to construct the null distribution, and
min_samples specifies the minimum number of samples
required for a trait–feature combination to be tested.
The returned object contains the results from both site- and protein-level analyses. Each row represents a glycan trait evaluated for a specific glycosylation site or protein and includes the estimated group difference and its associated statistical significance.
The complete result table can be filtered to identify trait–feature combinations showing evidence of altered heterogeneity between the two groups. For example, the following code displays results with an unadjusted p-value below 0.05.
res[res$pval < 0.05, ]## trait score_type feature group1
## 10 GlycanSize mu GTJESDSATTQFTTEIDAPK (TENR) Normal
## 67 Hexose mu GTJESDSATTQFTTEIDAPK (TENR) Normal
## 80 Hexose mu YJCTATNHIGTR (NCAM2) Normal
## 108 Hexose mu GTEWLVJSSR (CNTN1) Normal
## 146 HexNAc mu GTEWLVJSSR (CNTN1) Normal
## 188 Fucose mu GTEWLVJSSR (CNTN1) Normal
## 218 Antennas mu YQPIJSTHELGPLVDLK (NRCAM) Normal
## 222 Antennas mu GTEWLVJSSR (CNTN1) Normal
## 241 IsBisecting mu LAYAAIJDSR (DPP6) Normal
## 243 IsBisecting mu VNVVJSTLAEVHWDPVPLK (NRCAM) Normal
## 259 IsComplex mu QJITYLLK (OMGP) Normal
## 299 IsOligomannose mu ADGTVNQIEGEATPVJLTEPAKLEVK (APOD) Normal
## 305 IsOligomannose mu GTEWLVJSSR (CNTN1) Normal
## 336 IsC_Fucosed mu GTEWLVJSSR (CNTN1) Normal
## 339 GlycanSize h AGPJGTLFVADAYK (APMAP) Normal
## 354 GlycanSize h JSTKEEILAALEK (SAP) Normal
## 411 Hexose h JSTKEEILAALEK (SAP) Normal
## 445 Hexose h GTEWLVJSSR (CNTN1) Normal
## 483 HexNAc h GTEWLVJSSR (CNTN1) Normal
## 525 Fucose h GTEWLVJSSR (CNTN1) Normal
## 555 Antennas h YQPIJSTHELGPLVDLK (NRCAM) Normal
## 559 Antennas h GTEWLVJSSR (CNTN1) Normal
## 568 IsBisecting h QJITYLLK (OMGP) Normal
## 578 IsBisecting h LAYAAIJDSR (DPP6) Normal
## 580 IsBisecting h VNVVJSTLAEVHWDPVPLK (NRCAM) Normal
## 596 IsComplex h QJITYLLK (OMGP) Normal
## 642 IsOligomannose h GTEWLVJSSR (CNTN1) Normal
## 673 IsC_Fucosed h GTEWLVJSSR (CNTN1) Normal
## 689 Hexose mu NCAM2 Normal
## 801 Antennas h NCAM2 Normal
## 826 IsOligomannose h NCAM2 Normal
## group2 mean_group1 mean_group2 diff pval n_group1
## 10 Symptomatic 9.53108183 9.1728836 0.35819823 0.039960040 9
## 67 Symptomatic 3.58461718 3.4269841 0.15763305 0.020979021 9
## 80 Symptomatic 4.93779956 4.8675445 0.07025507 0.020979021 9
## 108 Symptomatic 4.77443311 4.4985570 0.27587611 0.009990010 7
## 146 Symptomatic 2.05493197 2.2002165 -0.14528448 0.006993007 7
## 188 Symptomatic 0.01360544 0.1139971 -0.10039167 0.007992008 7
## 218 Symptomatic 2.12934066 2.4107143 -0.28137363 0.014985015 5
## 222 Symptomatic 0.05493197 0.2002165 -0.14528448 0.008991009 7
## 241 Symptomatic 0.70277778 0.5973714 0.10540640 0.023976024 7
## 243 Symptomatic 0.06780303 0.1959936 -0.12819056 0.034965035 6
## 259 Symptomatic 0.50871291 0.4235209 0.08519198 0.049950050 10
## 299 Symptomatic 0.42916667 0.5568254 -0.12765873 0.035964036 6
## 305 Symptomatic 0.94506803 0.7997835 0.14528448 0.008991009 7
## 336 Symptomatic 0.01360544 0.1139971 -0.10039167 0.005994006 7
## 339 Symptomatic 0.33366480 0.5020795 -0.16841467 0.005994006 9
## 354 Symptomatic 0.65701594 0.5871896 0.06982631 0.038961039 9
## 411 Symptomatic 0.65701594 0.5871896 0.06982631 0.026973027 9
## 445 Symptomatic 0.27296402 0.6409248 -0.36796079 0.004995005 7
## 483 Symptomatic 0.04891136 0.1561117 -0.10720036 0.010989011 7
## 525 Symptomatic 0.01230969 0.1006561 -0.08834643 0.005994006 7
## 555 Symptomatic 0.10602530 0.2413903 -0.13536501 0.033966034 5
## 559 Symptomatic 0.04891136 0.1561117 -0.10720036 0.002997003 7
## 568 Symptomatic 0.24570239 0.2317307 0.01397174 0.013986014 10
## 578 Symptomatic 0.20456239 0.2336238 -0.02906141 0.037962038 7
## 580 Symptomatic 0.05802256 0.1481910 -0.09016840 0.016983017 6
## 596 Symptomatic 0.24539684 0.2329422 0.01245464 0.042957043 10
## 642 Symptomatic 0.04891136 0.1561117 -0.10720036 0.007992008 7
## 673 Symptomatic 0.01230969 0.1006561 -0.08834643 0.008991009 7
## 689 Symptomatic 4.68843240 4.4627765 0.22565588 0.014985015 7
## 801 Symptomatic 0.56999429 0.9040375 -0.33404317 0.048951049 7
## 826 Symptomatic 0.11922739 0.1858701 -0.06664270 0.047952048 7
## n_group2 method level
## 10 6 permutation site
## 67 6 permutation site
## 80 9 permutation site
## 108 4 permutation site
## 146 4 permutation site
## 188 4 permutation site
## 218 3 permutation site
## 222 4 permutation site
## 241 8 permutation site
## 243 8 permutation site
## 259 9 permutation site
## 299 5 permutation site
## 305 4 permutation site
## 336 4 permutation site
## 339 8 permutation site
## 354 7 permutation site
## 411 7 permutation site
## 445 4 permutation site
## 483 4 permutation site
## 525 4 permutation site
## 555 3 permutation site
## 559 4 permutation site
## 568 9 permutation site
## 578 8 permutation site
## 580 8 permutation site
## 596 9 permutation site
## 642 4 permutation site
## 673 4 permutation site
## 689 6 permutation protein
## 801 6 permutation protein
## 826 6 permutation protein
These results represent glycan traits whose heterogeneity differs between the Normal and Symptomatic groups at either the glycosylation-site or protein level. The corresponding analysis level can be identified from the relevant result column.
The analysis results can be visualized using a heatmap and a volcano plot.
plot_hscore_heatmap(res)
plot_hscore_volcano(res)
The heatmap summarizes group-associated heterogeneity patterns across selected trait–feature combinations, facilitating comparisons among proteins, glycosylation sites, and glycan traits.
The volcano plot displays the magnitude of each heterogeneity change together with its statistical significance. Trait–feature combinations with larger absolute group differences appear farther from zero on the horizontal axis, whereas those with stronger statistical evidence appear higher on the vertical axis.
In addition to the pre-defined glycan traits, glycoTraitR allows users to define custom glycan motifs of biological interest. These motifs are detected within glycan structures and can be incorporated directly into downstream trait analyses.
In this vignette, we will:
We first parse glycan structures into tree representations.
Internally, glycans are represented as graphs, where nodes correspond to
monosaccharides and edges represent glycosidic linkages.
# Example: parsed glycan trees from existing GPSM data
glycans <- lapply(gpsm$GlycanStructure, glycoTraitR:::pGlyco3_to_tree)We use the function build_glycan_igraph() to visualize
an example of glycan structure.
# visualize example structures
igraph_obj <- build_glycan_igraph(glycans[[1]])
plot_glycan_tree(igraph_obj)
This visualization highlights the branching structure and residue composition of a glycan, which is essential for understanding motif topology.
This example demonstrates how to define and detect a simple glycan motif consisting of three hexose (H) residues connected in series.
Here we define a linear trisaccharide motif:
"a-b", "b-c"
#### Example 1 ####
# (1) Select a glycan from pGlyco3 data
tree_full <- glycans[[2]]
g_full <- build_glycan_igraph(tree_full)
# (2) Define motif manually
motif <- list(
node = c("H", "H", "H"),
edge = c("a-b", "b-c")
)
g_motif <- build_glycan_igraph(motif)
# (3) Perform subgraph matching
type_levels <- union(
unique(V(g_full)$type),
unique(V(g_motif)$type)
)
n_match <- count_subgraph_isomorphisms(
g_motif, g_full,
method = "vf2",
vertex.color1 = factor(V(g_full)$type, levels=type_levels),
vertex.color2 = factor(V(g_motif)$type, levels=type_levels)
)
# (4) Visualize
par(mfrow = c(1, 2))
plot_glycan_tree(g_motif)
plot_glycan_tree(g_full)
## [1] "2 motif(s) found in the glycan"
The reported match count indicates how many times the specified motif occurs within the full glycan structure.
More complex motifs can also be defined, including branched structures and specific monosaccharide types such as fucose (F).
This example defines a branched motif containing Fucose:
#### Example 2 ####
# (1) Select a glycan
tree_full <- glycans[[6]]
g_full <- glycoTraitR::build_glycan_igraph(tree_full)
# (2) Symbolic motif definition
motif <- list(
node = c("H", "N", "F"),
edge = c("a-b", "b-c")
)
g_motif <- glycoTraitR::build_glycan_igraph(motif)
# (3) Subgraph matching
type_levels <- union(
unique(V(g_full)$type),
unique(V(g_motif)$type)
)
n_match <- igraph::count_subgraph_isomorphisms(
g_motif,
g_full,
method = "vf2",
vertex.color1 = factor(V(g_full)$type, levels = type_levels),
vertex.color2 = factor(V(g_motif)$type, levels = type_levels)
)
# (4) Visualize motif vs. full glycan
par(mfrow = c(1, 2))
plot_glycan_tree(g_motif)
plot_glycan_tree(g_full)
## [1] "1 motif(s) found in the glycan"
Multiple user-defined motifs can be supplied simultaneously.
Once defined, these motifs are treated as additional glycan traits and
are incorporated into the trait computation workflow.
user_motifs <- list(
LinearH3 = list(
node = c("H", "H", "H"),
edge = c("a-b", "b-c")
),
FucBranch = list(
node = c("H", "N", "F"),
edge = c("a-b", "b-c")
)
)Each user-defined motif can be input as an option.
set.seed(123)
res <- analyze_hscore_changes(
gpsm = gpsm,
from = "pGlyco3",
motifs = user_motifs,
meta = meta,
group_col = "Diagnosis",
group_levels = c("Normal", "Symptomatic"),
B = 1000,
min_samples = 3
)## Compute heterogeneity scores at each site and protein
## Test heterogeneity change at site
## Test heterogeneity change at protein
res[res$trait == "LinearH3" & res$pval < 0.05, ]## trait score_type feature group1 group2 mean_group1
## 377 LinearH3 mu HMJETSHTQGSLR (NTRK2) Normal Symptomatic 1.6766667
## 380 LinearH3 mu GTEWLVJSSR (CNTN1) Normal Symptomatic 1.7458617
## 787 LinearH3 h HMJETSHTQGSLR (NTRK2) Normal Symptomatic 0.4106247
## 790 LinearH3 h GTEWLVJSSR (CNTN1) Normal Symptomatic 0.3358212
## 905 LinearH3 mu NCAM2 Normal Symptomatic 1.6524975
## mean_group2 diff pval n_group1 n_group2 method level
## 377 1.4485450 0.2281217 0.03896104 5 6 permutation site
## 380 1.4430014 0.3028602 0.01098901 7 4 permutation site
## 787 0.6734827 -0.2628580 0.02897103 5 6 permutation site
## 790 0.7520359 -0.4162148 0.02197802 7 4 permutation site
## 905 1.4204154 0.2320821 0.02297702 7 6 permutation protein
Your motif counts will automatically appear as additional glycan traits in the trait matrices.
In this vignette, we demonstrated how to define custom glycan motifs, detect their occurrences within glycan structures, and incorporate them into the glycoTraitR trait analysis workflow.
## R version 4.5.2 (2025-10-31)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 22.04.2 LTS
##
## Matrix products: default
## BLAS: /opt/R/4.5.2/lib/R/lib/libRblas.so
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.10.0 LAPACK version 3.10.0
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
##
## time zone: Asia/Tokyo
## tzcode source: system (glibc)
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] igraph_2.2.1 glycoTraitR_0.1.1 BiocStyle_2.38.0
##
## loaded via a namespace (and not attached):
## [1] gtable_0.3.6 jsonlite_2.0.0 dplyr_1.1.4
## [4] compiler_4.5.2 BiocManager_1.30.26 Rcpp_1.1.0
## [7] tidyselect_1.2.1 parallel_4.5.2 jquerylib_0.1.4
## [10] systemfonts_1.3.1 scales_1.4.0 textshaping_1.0.4
## [13] yaml_2.3.10 fastmap_1.2.0 ggplot2_4.0.0
## [16] R6_2.6.1 labeling_0.4.3 patchwork_1.3.2
## [19] generics_0.1.4 knitr_1.51 htmlwidgets_1.6.4
## [22] ggrepel_0.9.6 tibble_3.3.0 bookdown_0.46
## [25] desc_1.4.3 bslib_0.9.0 pillar_1.11.1
## [28] RColorBrewer_1.1-3 rlang_1.1.6 utf8_1.2.6
## [31] cachem_1.1.0 xfun_0.56 fs_1.6.6
## [34] sass_0.4.10 S7_0.2.0 otel_0.2.0
## [37] cli_3.6.5 withr_3.0.2 pkgdown_2.2.0
## [40] magrittr_2.0.4 digest_0.6.37 grid_4.5.2
## [43] pbapply_1.7-4 rstudioapi_0.17.1 lifecycle_1.0.4
## [46] vctrs_0.6.5 evaluate_1.0.5 glue_1.8.0
## [49] farver_2.1.2 ragg_1.5.0 rmarkdown_2.30
## [52] pkgconfig_2.0.3 tools_4.5.2 htmltools_0.5.8.1