Source: TBA
TMT Proteomics Analysis Workflow
# 1. Install packages (run once)
install.packages(c("tidyverse","readr","janitor","pheatmap","ggplot2"))
install.packages("BiocManager")
BiocManager::install(c("limma","clusterProfiler","org.Hs.eg.db"))
library("dplyr")
library("tidyverse")
library("readr")
library("janitor")
library("limma")
library("pheatmap")
library("clusterProfiler")
library("org.Hs.eg.db")
library("ggplot2")
library("kableExtra")
library("beeswarm")
library("mitch")
library("gplots")
##
## ---------------------
## gplots 3.3.0 loaded:
## * Use citation('gplots') for citation info.
## * Homepage: https://talgalili.github.io/gplots/
## * Report issues: https://github.com/talgalili/gplots/issues
## * Ask questions: https://stackoverflow.com/questions/tagged/gplots
## * Suppress this message with: suppressPackageStartupMessages(library(gplots))
## ---------------------
##
## Attaching package: 'gplots'
## The following object is masked from 'package:IRanges':
##
## space
## The following object is masked from 'package:S4Vectors':
##
## space
## The following object is masked from 'package:stats':
##
## lowess
plexA <- read_tsv("abundance_protein_MD_plexA.tsv")
## Rows: 963 Columns: 27
## ── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────
## Delimiter: "\t"
## chr (8): Index, Gene, Protein, Protein ID, Entry Name, Protein Description,...
## dbl (19): NumberPSM, MaxPepProb, ReferenceIntensity, _126, _127N, _127C, _12...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
plexB <- read_tsv("abundance_protein_MD_plexB.tsv")
## Rows: 962 Columns: 27
## ── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────
## Delimiter: "\t"
## chr (8): Index, Gene, Protein, Protein ID, Entry Name, Protein Description,...
## dbl (19): NumberPSM, MaxPepProb, ReferenceIntensity, _126, _127N, _127C, _12...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
plexA <- janitor::clean_names(plexA)
plexB <- janitor::clean_names(plexB)
Keep relevant columns
Rename TMT channels to sample IDs
Merge Plex A and B.
plexA <- dplyr::select(plexA, protein, gene,
x126, x127n, x127c, x128n, x128c,
x129n, x129c, x130n, x130c,
x131n, x131c, x132n)
plexB <- dplyr::select(plexB, protein, gene,
x126, x127n, x127c, x128n, x128c,
x129n, x129c, x130n, x130c,
x131n, x131c, x132n)
# Rename TMT channels to sample IDs
annotationA <- c(
x126="19191", x127n="34629", x127c="34862",
x128n="40431", x128c="40475", x129n="35038",
x129c="34866", x130n="41436", x130c="41383",
x131n="40316", x131c="3746", x132n="102953"
)
annotationB <- c(
x126="40797", x127n="4177", x127c="103376",
x128n="47542", x128c="47442", x129n="42977",
x129c="43081", x130n="113835", x130c="113856",
x131n="19584", x131c="118117", x132n="118008"
)
colnames(plexA)[match(names(annotationA), colnames(plexA))] <- annotationA
colnames(plexB)[match(names(annotationB), colnames(plexB))] <- annotationB
# Merge Plex A and B
merged <- full_join(plexA, plexB, by=c("protein","gene"))
head(merged) %>%
kbl(caption="Proteomic data from fragpipe") %>%
kable_paper("hover", full_width = F)
| protein | gene | 19191 | 34629 | 34862 | 40431 | 40475 | 35038 | 34866 | 41436 | 41383 | 40316 | 3746 | 102953 | 40797 | 4177 | 103376 | 47542 | 47442 | 42977 | 43081 | 113835 | 113856 | 19584 | 118117 | 118008 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| sp|A0A075B6H7|KV37_HUMAN | IGKV3-7 | 25.20197 | 25.39573 | 25.43256 | 26.05771 | 25.05397 | 25.57650 | 25.65469 | 25.37295 | 25.65501 | 25.64185 | 25.43883 | 25.33301 | 30.46372 | 30.34873 | 30.21146 | 30.78558 | 30.36076 | 30.19026 | 30.28124 | 30.56661 | 29.76611 | 30.72821 | 30.20665 | 30.00076 |
| sp|A0A075B6H9|LV469_HUMAN | IGLV4-69 | 28.95035 | 29.82285 | 29.61003 | 29.53702 | 29.44966 | 28.84860 | 29.91425 | 29.41320 | 29.00432 | 28.83877 | 28.59919 | 29.14621 | 22.40007 | 21.18373 | 21.26245 | 21.90925 | 22.59531 | 21.24953 | 21.98843 | 21.22654 | 21.40015 | 22.00258 | 21.02142 | 21.46372 |
| sp|A0A075B6I0|LV861_HUMAN | IGLV8-61 | 27.53609 | 28.54878 | 26.58017 | 27.43782 | 27.43139 | 26.83964 | 27.26845 | 26.57449 | 28.21526 | 26.57432 | 26.75554 | NA | 25.58149 | 26.12823 | 26.52763 | 25.72071 | 26.59545 | 25.47399 | 26.13838 | 25.35584 | 25.89193 | 25.69072 | 25.72252 | 26.67365 |
| sp|A0A075B6I1|LV460_HUMAN | IGLV4-60 | 21.13980 | NA | 20.95866 | 21.90418 | 19.86279 | 21.18880 | 21.20105 | 20.12885 | 20.95064 | 21.09826 | 20.35881 | NA | 27.79615 | 26.93927 | 25.90896 | 26.48209 | 28.84106 | 26.96525 | 28.56674 | 27.15404 | 27.20759 | 27.49989 | 27.18150 | 27.81810 |
| sp|A0A075B6J9|LV218_HUMAN | IGLV2-18 | 22.38769 | 25.30212 | 25.12898 | 24.02298 | 23.89291 | 24.49498 | 24.70158 | 24.32961 | 24.30966 | 24.58185 | 23.43995 | 23.82350 | 27.34292 | 26.35223 | 24.59685 | 26.37291 | 25.30866 | 25.64357 | 26.10869 | 25.59368 | 27.73543 | 25.64763 | 26.16884 | 26.54800 |
| sp|A0A075B6K0|LV316_HUMAN | IGLV3-16 | 21.37483 | 22.29617 | 21.39598 | 21.69973 | 21.51293 | 23.78554 | 22.11370 | 22.61187 | 20.93010 | 22.14908 | 20.87886 | 20.41397 | 20.66449 | 22.03552 | 22.04962 | 21.69365 | 21.55941 | 21.37521 | 22.05910 | 22.66605 | 21.11006 | 20.78442 | 21.76661 | 21.22903 |
# Create expression matrix
expr <- as.data.frame(merged)
rownames(expr) <- paste(expr$gene,expr$protein)
expr$protein <- NULL
expr$gene <- NULL
First log transform data and then filter protein, and do quantile normalisation.
# Log2 transform intensities
expr_log <- log2(expr + 1)
# Filter proteins (present in >=50% of samples)
keep <- rowSums(!is.na(expr_log)) >= ncol(expr_log)*0.5
expr_filtered <- expr_log[keep, ]
# Quantile normalization
expr_norm <- normalizeBetweenArrays(expr_filtered, method="quantile")
# QC: Missing value percentage
missing_percent <- colMeans(is.na(expr_norm))*100
print(missing_percent)
## 19191 34629 34862 40431 40475 35038 34866 41436
## 10.28761 15.04425 12.38938 15.15487 15.04425 10.84071 10.95133 13.82743
## 41383 40316 3746 102953 40797 4177 103376 47542
## 12.50000 15.70796 11.83628 15.37611 15.26549 13.49558 21.01770 13.71681
## 47442 42977 43081 113835 113856 19584 118117 118008
## 19.13717 14.60177 14.15929 19.69027 15.04425 15.48673 19.57965 25.33186
Intensity distribution plot
expr_long <- as.data.frame(expr_norm) %>%
pivot_longer(cols = everything(),
names_to = "Sample",
values_to = "Intensity") %>%
filter(is.finite(Intensity)) # remove NA / Inf / -Inf
ggplot(expr_long, aes(x = Intensity)) +
geom_density(fill = "steelblue", alpha = 0.4) +
facet_wrap(~Sample) +
theme_bw() +
ggtitle("Intensity Distribution per Sample")
Combined intensity distribution plot
expr_long <- as.data.frame(expr_norm) %>%
pivot_longer(cols = everything(),
names_to = "Sample",
values_to = "Intensity") %>%
filter(is.finite(Intensity)) # remove NA/Inf/-Inf
ggplot(expr_long, aes(x = Intensity, color = Sample)) +
geom_density(size = 1) +
theme_bw() +
ggtitle("Combined Intensity Distribution of All Samples") +
xlab("Log2 Intensity") +
ylab("Density")
QC: PCA plot
# Remove infinite values
expr_norm[is.infinite(expr_norm)] <- NA
# Impute missing values (median)
expr_pca <- expr_norm
for(i in 1:ncol(expr_pca)){
expr_pca[is.na(expr_pca[,i]), i] <- median(expr_pca[,i], na.rm=TRUE)
}
# PCA
pca <- prcomp(t(expr_pca))
pca_df <- data.frame(
PC1 = pca$x[,1],
PC2 = pca$x[,2],
Sample = colnames(expr_pca)
)
# Add group info
group <- factor(c(
"Case","Control","Case","Control",
"Case","Control","Case","Control",
"Case","Control","Case","Control",
"Case","Control","Case","Control",
"Case","Control","Case","Control",
"Case","Control","Case","Control"
))
pca_df$Group <- group
# Plot
library(ggplot2)
ggplot(pca_df, aes(PC1, PC2, color=Group, label=Sample)) +
geom_point(size=3) +
geom_text(vjust=1.5) +
theme_bw() +
ggtitle("PCA of Samples")
Sample correlation heatmap
cor_matrix <- cor(expr_norm, use="pairwise.complete.obs")
pheatmap(cor_matrix, main="Sample Correlation Heatmap")
Set up the design matrix and then use limma to run the stat test.
group <- factor(c(
"Case","Control","Case","Control",
"Case","Control","Case","Control",
"Case","Control","Case","Control",
"Case","Control","Case","Control",
"Case","Control","Case","Control",
"Case","Control","Case","Control"
))
design <- model.matrix(~group)
fit <- lmFit(expr_norm, design)
fit <- eBayes(fit)
results <- topTable(fit, coef=2, number=Inf)
head(results,20) %>%
kbl(caption="Top 20 most significant differences") %>%
kable_paper("hover", full_width = F)
| logFC | AveExpr | t | P.Value | adj.P.Val | B | |
|---|---|---|---|---|---|---|
| ENTPD5 sp|O75356|ENTP5_HUMAN | -0.0824043 | 4.365370 | -4.020203 | 0.0016686 | 0.5779301 | -0.9514331 |
| HSPD1 sp|P10809|CH60_HUMAN | 0.1342293 | 4.276747 | 3.608039 | 0.0025558 | 0.5779301 | -1.4393077 |
| ITM2B sp|Q9Y287|ITM2B_HUMAN | 0.0645200 | 4.304086 | 3.672916 | 0.0031434 | 0.5779301 | -1.5269652 |
| VPS29 sp|Q9UBQ0|VPS29_HUMAN | 0.1115886 | 4.261511 | 3.661900 | 0.0032077 | 0.5779301 | -1.5454004 |
| CA3 sp|P07451|CAH3_HUMAN | -0.1004160 | 4.445305 | -3.516887 | 0.0041916 | 0.5779301 | -1.7888697 |
| ARRB1 sp|P49407|ARRB1_HUMAN | -0.0981963 | 4.432147 | -3.445170 | 0.0039019 | 0.5779301 | -1.7967856 |
| ITGA6 sp|P23229|ITA6_HUMAN | 0.1266236 | 4.408744 | 3.419608 | 0.0050193 | 0.5779301 | -1.9528870 |
| PSMF1 sp|Q92530|PSMF1_HUMAN | -0.1013330 | 4.080828 | -3.409490 | 0.0051144 | 0.5779301 | -1.9699710 |
| INF2 sp|Q27J81|INF2_HUMAN | 0.0964987 | 4.423766 | 3.100175 | 0.0068328 | 0.5854217 | -2.3479025 |
| TPM3 sp|P06753|TPM3_HUMAN | 0.1232341 | 4.554235 | 3.088933 | 0.0092897 | 0.5854217 | -2.5124136 |
| DBN1 sp|Q16643|DREB_HUMAN | 0.1015202 | 4.431206 | 3.081373 | 0.0094217 | 0.5854217 | -2.5192803 |
| PRCP sp|P42785|PCP_HUMAN | -0.0731277 | 4.354974 | -3.083102 | 0.0093913 | 0.5854217 | -2.5222820 |
| SFTPB sp|P07988|PSPB_HUMAN | -0.0963832 | 4.417397 | -3.057247 | 0.0098555 | 0.5854217 | -2.5660301 |
| CSF1R sp|P07333|CSF1R_HUMAN | -0.0999052 | 4.385271 | -2.938158 | 0.0123076 | 0.5854217 | -2.7672585 |
| DKK3 sp|Q9UBP4|DKK3_HUMAN | 0.0734493 | 4.302518 | 2.932529 | 0.0124375 | 0.5854217 | -2.7767533 |
| PPM1F sp|P49593|PPM1F_HUMAN | -0.1030720 | 4.160987 | -2.927306 | 0.0125593 | 0.5854217 | -2.7855632 |
| IGKV2D-29 sp|A0A075B6S2|KVD29_HUMAN | -0.0745215 | 4.784014 | -2.923371 | 0.0126518 | 0.5854217 | -2.7922006 |
| IGF1 sp|P05019|IGF1_HUMAN | -0.0548494 | 4.515201 | -2.910803 | 0.0129518 | 0.5854217 | -2.8133887 |
| ARPC4 sp|P59998|ARPC4_HUMAN | 0.1267741 | 4.507737 | 2.853209 | 0.0126876 | 0.5854217 | -2.8552706 |
| GM2A sp|P17900|SAP3_HUMAN | -0.0676636 | 4.384216 | -2.838208 | 0.0148284 | 0.6362363 | -2.9355862 |
saveRDS(results,"DE_results.rds")
write.csv(results, "Differential_expression_results.csv")
ggplot(results, aes(x=logFC, y=-log10(P.Value))) +
geom_point(alpha=0.6) +
theme_bw() +
xlab("log2 Fold Change") +
ylab("-log10 P-value") +
ggtitle("Volcano Plot")
gene <- rownames(results)[1]
pex <- expr_norm[which(rownames(expr_norm) == gene),]
pex_case <- pex[which(group=="Case")]
pex_ctrl <- pex[which(group=="Control")]
pl <- list("Ctrl"=pex_ctrl,"Case"=pex_case)
pl
## $Ctrl
## 34629 40431 35038 41436 40316 102953 4177 47542
## NA NA NA NA NA NA 4.290280 4.317761
## 42977 113835 19584 118008
## 4.314943 4.373970 4.286314 4.361736
##
## $Case
## 19191 34862 40475 34866 41383 3746 40797 103376
## NA NA NA NA NA NA 4.418528 4.408456
## 47442 43081 113856 118117
## 4.422823 4.344689 4.432390 4.412545
boxplot(pl,col="white",cex=0,ylab="normalised protein expression",main=gene)
beeswarm(pl,add=TRUE,cex=2,col="darkgray",pch=19)
null <- lapply(1:10,function(i) {
gene <- rownames(results)[i]
pex <- expr_norm[which(rownames(expr_norm) == gene),]
pex_case <- pex[which(group=="Case")]
pex_ctrl <- pex[which(group=="Control")]
pl <- list("Ctrl"=pex_ctrl,"Case"=pex_case)
pl
boxplot(pl,col="white",cex=0,ylab="normalised protein expression",main=gene)
beeswarm(pl,add=TRUE,cex=2,col="darkgray",pch=19)
})
topgenes <- rownames(head(results,30))
rowidx <- which(rownames(expr_norm) %in% topgenes)
topmx <- expr_norm[rowidx,]
topmx <- topmx+0.01
topmx[is.na(topmx)] <- 0
colnames(topmx) <- paste(group,colnames(topmx))
colfunc <- colorRampPalette(c("blue", "white", "red"))
heatmap.2(topmx, main="Top proteins", scale="row", col = colfunc(25), trace="none",margin=c(9,13),cexRow=0.7,cexCol=0.8)
reactome <- gmt_import("ReactomePathways_2026-04-02.gmt")
head(reactome)
## $`2-LTR circle formation`
## [1] "BANF1" "HMGA1" "LIG4" "PSIP1" "XRCC4" "XRCC5" "XRCC6"
## [8] "gag" "gag-pol" "rev" "vif" "vpr" "vpu"
##
## $`3-Methylcrotonyl-CoA carboxylase deficiency`
## [1] "MCCC1" "MCCC2"
##
## $`3-hydroxyisobutyryl-CoA hydrolase deficiency`
## [1] "HIBCH"
##
## $`3-methylglutaconic aciduria`
## [1] "AUH"
##
## $`5-Phosphoribose 1-diphosphate biosynthesis`
## [1] "PRPS1" "PRPS1L1" "PRPS2"
##
## $`ABC transporter disorders`
## [1] "ABCA1" "ABCA12" "ABCA3" "ABCB11" "ABCB4" "ABCB6" "ABCC2" "ABCC6"
## [9] "ABCC8" "ABCC9" "ABCD1" "ABCD4" "ABCG5" "ABCG8" "ADRM1" "APOA1"
## [17] "CFTR" "DERL1" "DERL2" "DERL3" "ERLEC1" "ERLIN1" "ERLIN2" "KCNJ11"
## [25] "LMBRD1" "OS9" "PSMA1" "PSMA2" "PSMA3" "PSMA4" "PSMA5" "PSMA6"
## [33] "PSMA7" "PSMB1" "PSMB2" "PSMB3" "PSMB4" "PSMB5" "PSMB6" "PSMB7"
## [41] "PSMC1" "PSMC2" "PSMC3" "PSMC4" "PSMC5" "PSMC6" "PSMD1" "PSMD11"
## [49] "PSMD12" "PSMD13" "PSMD14" "PSMD2" "PSMD3" "PSMD6" "PSMD7" "PSMD8"
## [57] "RNF185" "RNF5" "RPS27A" "SEL1L" "SEM1" "UBA52" "UBB" "UBC"
## [65] "VCP"
gt <- data.frame(rownames(results))
gt$genename <- sapply(strsplit(gt[,1]," "),"[[",1)
y <- mitch_import(x=results, DEtype="limma",geneTable=gt)
## The input is a single dataframe; one contrast only. Converting
## it to a list for you.
## Note: Mean no. genes in input = 904
## Note: no. genes in output = 904
## Note: estimated proportion of input genes in output = 1
mres <- mitch_calc(x=y, genesets=reactome, priority="effect", minsetsize=5, cores=4)
## Note: Enrichments with large effect sizes may not be
## statistically significant.
head(mres$enrichment_result,10) %>%
kbl(caption="Top results by enrichment score") %>%
kable_paper("hover", full_width = F)
| set | setSize | pANOVA | s.dist | p.adjustANOVA | |
|---|---|---|---|---|---|
| 327 | Mitochondrial protein degradation | 6 | 0.0065206 | 0.6429102 | 0.3298240 |
| 501 | Sensory processing of sound | 5 | 0.0184966 | 0.6097887 | 0.4958357 |
| 155 | Diseases of carbohydrate metabolism | 6 | 0.0104326 | -0.6054195 | 0.3925270 |
| 548 | Syndecan interactions | 10 | 0.0013242 | 0.5885906 | 0.2032772 |
| 151 | Diseases associated with O-glycosylation of proteins | 9 | 0.0026981 | 0.5796400 | 0.2455375 |
| 433 | RUNX1 regulates genes involved in megakaryocyte differentiation and platelet function | 5 | 0.0317934 | 0.5559511 | 0.5629302 |
| 230 | Glutathione conjugation | 5 | 0.0389872 | 0.5345940 | 0.6011561 |
| 194 | Folding of actin by CCT/TriC | 6 | 0.0255122 | 0.5282108 | 0.5389579 |
| 45 | Association of TriC/CCT with target proteins during biosynthesis | 6 | 0.0287906 | 0.5170750 | 0.5515299 |
| 378 | Phospholipid metabolism | 5 | 0.0496776 | 0.5083426 | 0.6565385 |
mres2 <- mitch_calc(x=y, genesets=reactome, priority="significance", minsetsize=5, cores=4)
## Note: When prioritising by significance (ie: small
## p-values), large effect sizes might be missed.
head(mres2$enrichment_result,10) %>%
kbl(caption="Top results by statistical significance") %>%
kable_paper("hover", full_width = F)
| set | setSize | pANOVA | s.dist | p.adjustANOVA | |
|---|---|---|---|---|---|
| 197 | Formation of the cornified envelope | 28 | 0.0007394 | -0.3733692 | 0.2032772 |
| 282 | Keratinization | 28 | 0.0007394 | -0.3733692 | 0.2032772 |
| 548 | Syndecan interactions | 10 | 0.0013242 | 0.5885906 | 0.2032772 |
| 317 | Metabolism of lipids | 30 | 0.0013841 | 0.3423341 | 0.2032772 |
| 354 | Non-integrin membrane-ECM interactions | 19 | 0.0016883 | 0.4198037 | 0.2032772 |
| 151 | Diseases associated with O-glycosylation of proteins | 9 | 0.0026981 | 0.5796400 | 0.2455375 |
| 374 | Peptide hormone metabolism | 15 | 0.0028551 | -0.4479190 | 0.2455375 |
| 88 | Cellular responses to stimuli | 86 | 0.0045506 | 0.1855348 | 0.3298240 |
| 383 | Platelet Adhesion to exposed collagen | 10 | 0.0060991 | 0.5031320 | 0.3298240 |
| 168 | EPH-Ephrin signaling | 20 | 0.0061924 | 0.3571267 | 0.3298240 |
For reproducibility.
sessionInfo()
## R version 4.5.3 (2026-03-11)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 24.04.4 LTS
##
## Matrix products: default
## BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
## LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so; LAPACK version 3.12.0
##
## locale:
## [1] LC_CTYPE=en_AU.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=en_AU.UTF-8 LC_COLLATE=en_AU.UTF-8
## [5] LC_MONETARY=en_AU.UTF-8 LC_MESSAGES=en_AU.UTF-8
## [7] LC_PAPER=en_AU.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=en_AU.UTF-8 LC_IDENTIFICATION=C
##
## time zone: Australia/Melbourne
## tzcode source: system (glibc)
##
## attached base packages:
## [1] stats4 stats graphics grDevices utils datasets methods
## [8] base
##
## other attached packages:
## [1] gplots_3.3.0 mitch_1.20.0 beeswarm_0.4.0
## [4] kableExtra_1.4.0 org.Hs.eg.db_3.21.0 AnnotationDbi_1.70.0
## [7] IRanges_2.42.0 S4Vectors_0.46.0 Biobase_2.68.0
## [10] BiocGenerics_0.54.1 generics_0.1.4 clusterProfiler_4.16.0
## [13] pheatmap_1.0.13 limma_3.64.3 janitor_2.2.1
## [16] lubridate_1.9.5 forcats_1.0.1 stringr_1.6.0
## [19] purrr_1.2.1 readr_2.1.6 tidyr_1.3.2
## [22] tibble_3.3.1 ggplot2_4.0.2 tidyverse_2.0.0
## [25] dplyr_1.2.0
##
## loaded via a namespace (and not attached):
## [1] RColorBrewer_1.1-3 rstudioapi_0.18.0 jsonlite_2.0.0
## [4] magrittr_2.0.4 ggtangle_0.1.1 farver_2.1.2
## [7] rmarkdown_2.30 fs_1.6.6 vctrs_0.7.1
## [10] memoise_2.0.1 ggtree_3.16.3 htmltools_0.5.9
## [13] gridGraphics_0.5-1 sass_0.4.10 KernSmooth_2.23-26
## [16] bslib_0.10.0 htmlwidgets_1.6.4 plyr_1.8.9
## [19] echarts4r_0.5.0 cachem_1.1.0 igraph_2.2.2
## [22] mime_0.13 lifecycle_1.0.5 pkgconfig_2.0.3
## [25] Matrix_1.7-4 R6_2.6.1 fastmap_1.2.0
## [28] gson_0.1.0 shiny_1.12.1 GenomeInfoDbData_1.2.14
## [31] snakecase_0.11.1 digest_0.6.39 aplot_0.2.9
## [34] enrichplot_1.28.4 colorspace_2.1-2 GGally_2.4.0
## [37] patchwork_1.3.2 textshaping_1.0.4 RSQLite_2.4.6
## [40] labeling_0.4.3 timechange_0.4.0 httr_1.4.8
## [43] compiler_4.5.3 bit64_4.6.0-1 withr_3.0.2
## [46] S7_0.2.1 BiocParallel_1.42.2 DBI_1.2.3
## [49] ggstats_0.12.0 R.utils_2.13.0 MASS_7.3-65
## [52] rappdirs_0.3.4 caTools_1.18.3 gtools_3.9.5
## [55] tools_4.5.3 otel_0.2.0 ape_5.8-1
## [58] httpuv_1.6.16 R.oo_1.27.1 glue_1.8.0
## [61] promises_1.5.0 nlme_3.1-168 GOSemSim_2.34.0
## [64] grid_4.5.3 reshape2_1.4.5 fgsea_1.34.2
## [67] gtable_0.3.6 tzdb_0.5.0 R.methodsS3_1.8.2
## [70] data.table_1.18.2.1 hms_1.1.4 xml2_1.5.2
## [73] XVector_0.48.0 ggrepel_0.9.6 pillar_1.11.1
## [76] vroom_1.7.0 yulab.utils_0.2.4 later_1.4.6
## [79] splines_4.5.3 treeio_1.32.0 lattice_0.22-9
## [82] bit_4.6.0 tidyselect_1.2.1 GO.db_3.21.0
## [85] Biostrings_2.76.0 knitr_1.51 gridExtra_2.3
## [88] svglite_2.2.2 xfun_0.56 statmod_1.5.1
## [91] stringi_1.8.7 UCSC.utils_1.4.0 statnet.common_4.13.0
## [94] lazyeval_0.2.2 ggfun_0.2.0 yaml_2.3.12
## [97] evaluate_1.0.5 codetools_0.2-20 qvalue_2.40.0
## [100] ggplotify_0.1.3 cli_3.6.5 xtable_1.8-4
## [103] systemfonts_1.3.1 jquerylib_0.1.4 network_1.20.0
## [106] dichromat_2.0-0.1 Rcpp_1.1.1 GenomeInfoDb_1.44.3
## [109] coda_0.19-4.1 png_0.1-8 parallel_4.5.3
## [112] blob_1.3.0 DOSE_4.2.0 bitops_1.0-9
## [115] viridisLite_0.4.3 tidytree_0.4.7 scales_1.4.0
## [118] crayon_1.5.3 rlang_1.1.7 cowplot_1.2.0
## [121] fastmatch_1.1-8 KEGGREST_1.48.1