params
## $rds150
## [1] "data/ipms_150_sce.rds"
##
## $coords150
## [1] "data/visnetwork_coords_150.csv"
##
## $rds500
## [1] "data/ipms_500_sce.rds"
##
## $coords500
## [1] "data/visnetwork_coords_500.csv"
##
## $rds150untag
## [1] "data/ipms_150_untag_sce.rds"
##
## $interactors
## [1] "data/Gene_list_TFinteractors_Pombase20240226.txt"
##
## $idmap
## [1] "data/id_mapping_table.txt"
##
## $rad24_rad25_tbl
## [1] "data/FigS6_Rad24_Rad25_interactingTFs_list_motifs.txt"
suppressPackageStartupMessages({
library(visNetwork)
library(SingleCellExperiment)
library(dplyr)
library(ggplot2)
library(igraph)
library(shiny)
library(cowplot)
library(ggplotify)
library(ggraph)
library(latex2exp)
library(tidygraph)
library(ggrepel)
library(ComplexHeatmap)
library(flextable)
library(kableExtra)
library(ggupset)
library(tidyr)
library(jsonlite)
})
source("params/plot_settings.R")
source("params/get_testres_function.R")
source("params/mapping_functions.R")
source("params/ipms_params.R")
w_trad <- 84 # heatmap body width (mm)
h_trad <- 178 # total heatmap height (mm)
fs <- 6 # small font size
fl <- 10 # large font size
ft <- 12 # title font size
Here we load SingleCellExperiment objects corresponding to the low- and high-salt IP-MS experiments, as well as an object corresponding to the low-salt experiments, where each condition was compared to the untagged controls rather than the large complement group as in the other two objects.
sce150 <- readRDS(params$rds150)
sce500 <- readRDS(params$rds500)
sce150untag <- readRDS(params$rds150untag)
We also load a table with mappings between different types of feature identifiers, and a table with known, annotated physical interactions (obtained from PomBase).
idmap <- read.delim(params$idmap)
interactors <- read.delim(params$interactors) |>
dplyr::select(Systematic.ID, Gene.name, Physical.interactors) |>
tidyr::separate_rows(Physical.interactors, sep = ",") |>
dplyr::mutate(Gene.name = .capitalize(Gene.name),
Physical.interactors = .capitalize(Physical.interactors))
## Overwrite the get_legend function from cowplot temporarily,
## since the cowplot one doesn't work with ggplot2 3.5.0
## see https://github.com/wilkelab/cowplot/issues/202
get_legend <- function(plot, legend = NULL) {
gt <- ggplotGrob(plot)
pattern <- "guide-box"
if (!is.null(legend)) {
pattern <- paste0(pattern, "-", legend)
}
indices <- grep(pattern, gt$layout$name)
not_empty <- !vapply(
gt$grobs[indices],
inherits, what = "zeroGrob",
FUN.VALUE = logical(1)
)
indices <- indices[not_empty]
if (length(indices) > 0) {
return(gt$grobs[[indices[1]]])
}
return(NULL)
}
To define the similarity between two proteins, the following procedure is used: Let \(t_{ij}\) and \(padj_{ij}\) denote the t-statistic and adjusted p-value for protein \(i\) in comparison \(j\), respectively. Then define \[\tilde{t}_{ij} = \left\{\begin{array}{cl} 0 & \quad \textrm{if } t_{ij} <= 0 \textrm{ or } padj_{ij} > 0.1 \\ t_{ij} & \quad \textrm{otherwise} \end{array}\right.\]
The similarity between proteins \(i\) and \(k\) is then defined by \[sim_{ik} = \frac{\sum_{j=1}^N\tilde{t}_{ij}\tilde{t}_{kj}}{max\left(\sum_{j=1}^N\tilde{t}_{ij}, \sum_{j=1}^N\tilde{t}_{kj}\right)}\]
or, if written in another way: \[sim_{ik} = min\left(\frac{\sum_{j=1}^N\tilde{t}_{ij}\tilde{t}_{kj}}{\sum_{j=1}^N\tilde{t}_{ij}},\frac{\sum_{j=1}^N\tilde{t}_{ij}\tilde{t}_{kj}}{\sum_{j=1}^N\tilde{t}_{kj}}\right)\] it can be interpreted as the smallest of two weighted means.
The following helper function extracts t-statistics and adjusted p-values and calculates the truncated values mentioned above (\(\tilde{t}\)).
## Extract t-statistics and adjusted p-values and threshold
getTruncT <- function(sce, adjpThr = 0.1) {
## Extract adjusted p-values and log-fold changes
tc <- .getTestCols(sce)
adjpvals <- tc$adjp
tstats <- tc$tstat
colnames(adjpvals) <- .getProteinNameFromComparison(colnames(adjpvals))
colnames(tstats) <- .getProteinNameFromComparison(colnames(tstats))
adjpvals <- as.matrix(adjpvals[, grep("untagged|Untagged", colnames(adjpvals), invert = TRUE)])
tstats <- as.matrix(tstats[, grep("untagged|Untagged", colnames(tstats), invert = TRUE)])
stopifnot(colnames(adjpvals) == colnames(tstats),
rownames(adjpvals) == rownames(tstats))
## Need to pass a relatively loose significance threshold in at least one IP
## (don't want things to be similar just because they are weakly but consistently
## changing in many IPs)
tstats[adjpvals > adjpThr] <- 0
tstats[tstats <= 0] <- 0
tstats[is.na(tstats)] <- 0
tstats
}
We also define a function to calculate the similarities between each pair of proteins.
## Helper function to get matrix of similarities
simsFromResults <- function(sce, adjpThr = 0.1) {
tstats <- getTruncT(sce = sce, adjpThr = adjpThr)
simil <- tstats %*% t(tstats)
simil0 <- simil
for (i in seq_len(nrow(simil))) {
for (j in seq(i, ncol(simil))) {
simil[i, j] <- simil0[i, j] / max(sum(tstats[i, ]), sum(tstats[j, ]))
simil[j, i] <- simil0[j, i] / max(sum(tstats[i, ]), sum(tstats[j, ]))
}
}
simil[is.na(simil)] <- 0
## Don't need self-connections
diag(simil) <- 0
stopifnot(rownames(simil) == colnames(simil))
list(simil = simil, tstats = tstats, TFs = colnames(tstats))
}
To illustrate, let’s calculate the similarity for a specific example pair (Atf1 and Pcr1):
tmp <- getTruncT(sce = sce150, adjpThr = 0.1)[c("Atf1", "Pcr1"), ]
round(tmp[, colSums(tmp) != 0], 1)
## Gaf1 Hsf1 Atf1 Pcr1
## Atf1 3.0 2.4 12.2 8.4
## Pcr1 2.3 2.5 7.2 6.9
\[sim_{\textrm{atf1,pcr1}} = \min\left(\frac{3\cdot2.3+2.4\cdot2.5+12.2\cdot7.2+8.4\cdot6.9}{2.3+2.5+7.2+6.9},\frac{3\cdot2.3+2.4\cdot2.5+12.2\cdot7.2+8.4\cdot6.9}{3+2.4+12.2+8.4}\right) = min\left(8.4,6.1\right) = 6.1\]
simsFromResults(sce150[c("Atf1", "Pcr1"), ], adjpThr = 0.1)$simil
## Atf1 Pcr1
## Atf1 0.000000 6.114673
## Pcr1 6.114673 0.000000
Next, we calculate similarities for all pairs of proteins in each of the data sets.
simil150 <- simsFromResults(sce150, adjpThr = 0.1)
simil500 <- simsFromResults(sce500, adjpThr = 0.1)
maxSimil <- round(max(max(simil150$simil, na.rm = TRUE),
max(simil500$simil, na.rm = TRUE)), 1)
Given the matrix of similarities calculated above, we create a graph by first thresholding the similarities (setting all values below a given threshold to 0), and then considering the remaining (non-zero) values in the matrix as representing edges in the graph. Thus, two proteins in the graph are connected if their enrichment patterns across the IP experiments are similar. Only graph components with at least two proteins (i.e., no singletons) are displayed.
createNetwork <- function(similList, threshold, known_interactors, settings = "igraph") {
## Get similarity matrix and apply threshold
simil <- similList$simil
tfs <- similList$TFs
simil[simil < threshold] <- 0
simil[is.na(simil)] <- 0
## Create graph
gr <- graph_from_adjacency_matrix(simil, weighted = TRUE)
gr <- as.undirected(gr, mode = "collapse", edge.attr.comb = list(weight = "mean"))
## Remove singletons
comps <- components(gr)
too_small <- which(table(comps$membership) < 2)
keep <- V(gr)[!(comps$membership %in% too_small)]
gr <- induced_subgraph(gr, keep)
## Set attributes for vertices and edges
## Need col2hex here since visNetwork doesn't understand all R colors (e.g. gray70)
V(gr)$color <- gplots::col2hex(bg_color)
V(gr)$color[names(V(gr)) %in% tfs] <- main_colors[5]
V(gr)$vertexclass <- "other"
V(gr)$vertexclass[names(V(gr)) %in% tfs] <- "Bait"
if (settings == "visNetwork") {
V(gr)$shape <- "triangle"
V(gr)$size <- 15
V(gr)$label.cex = 2.08
} else if (settings == "igraph") {
V(gr)$shape <- "circle"
} else {
stop("Unknown 'settings' parameter")
}
V(gr)$shape[names(V(gr)) %in% tfs] <- "square"
E(gr)$value <- E(gr)$weight
E(gr)$width <- E(gr)$weight / max(simil) * 1.5
## Indicate annotated physical interactions
eL <- as_edgelist(gr)
for (i in seq_along(E(gr))) {
v1 <- eL[i, 1]
v2 <- eL[i, 2]
tmp <- known_interactors |>
dplyr::filter(((Systematic.ID == v1 | Gene.name == v1) &
Physical.interactors == v2) |
((Systematic.ID == v2 | Gene.name == v2) &
Physical.interactors == v1))
if (nrow(tmp) == 0) {
## Novel interaction
## One of the elements is a transcription factor -> color orange
if (v1 %in% tfs || v2 %in% tfs) {
E(gr)[i]$color <- main_colors[3]
E(gr)[i]$edgeclass <- "Unannotated TF interaction"
} else{
E(gr)[i]$color <- gplots::col2hex(na_color)
E(gr)[i]$edgeclass <- "Other"
}
} else {
E(gr)[i]$color <- gplots::col2hex(na_color)
E(gr)[i]$edgeclass <- "Other"
}
}
E(gr)$edgeclass <- factor(E(gr)$edgeclass,
levels = c("Unannotated TF interaction",
"Other"))
gr
}
Next, we create networks for the low- and high-salt experiments.
gr150 <- createNetwork(similList = simil150, threshold = 6,
known_interactors = interactors, settings = "igraph")
gr500 <- createNetwork(similList = simil500, threshold = 6,
known_interactors = interactors, settings = "igraph")
We export networks (with a lower similarity threshold, to allow for interactive exploration) for use by TFexplorer.
gr150tfx <- createNetwork(similList = simil150, threshold = 3,
known_interactors = interactors, settings = "igraph")
gr500tfx <- createNetwork(similList = simil500, threshold = 3,
known_interactors = interactors, settings = "igraph")
## 150 mM NaCl
n150 <- as_tbl_graph(gr150tfx) |>
activate(nodes) |>
data.frame() |>
mutate(idx = seq_along(name))
e150 <- as_tbl_graph(gr150tfx) |>
activate(edges) |>
data.frame() |>
left_join(n150 |> select(name, idx) |> rename(from = idx, from_name = name),
by = "from") |>
left_join(n150 |> select(name, idx) |> rename(to = idx, to_name = name),
by = "to")
exp150 <- list(
nodes = lapply(seq_len(nrow(n150)), function(i) {
list(id = n150$name[i],
label = n150$name[i],
value = 1)
}),
edges = lapply(seq_len(nrow(e150)), function(i) {
list(source = e150$from_name[i],
target = e150$to_name[i],
value = e150$value[i])
})
)
exp150 <- toJSON(exp150,
pretty = TRUE,
auto_unbox = TRUE)
write(exp150, file = "data/networkData_150mMSalt.json")
## 500 mM NaCl
n500 <- as_tbl_graph(gr500tfx) |>
activate(nodes) |>
data.frame() |>
mutate(idx = seq_along(name))
e500 <- as_tbl_graph(gr500tfx) |>
activate(edges) |>
data.frame() |>
left_join(n500 |> select(name, idx) |> rename(from = idx, from_name = name),
by = "from") |>
left_join(n500 |> select(name, idx) |> rename(to = idx, to_name = name),
by = "to")
exp500 <- list(
nodes = lapply(seq_len(nrow(n500)), function(i) {
list(id = n500$name[i],
label = n500$name[i],
value = 1)
}),
edges = lapply(seq_len(nrow(e500)), function(i) {
list(source = e500$from_name[i],
target = e500$to_name[i],
value = e500$value[i])
})
)
exp500 <- toJSON(exp500,
pretty = TRUE,
auto_unbox = TRUE)
write(exp500, file = "data/networkData_500mMSalt.json")
We extract all IPs where either Rad24 or Rad25 are pulled down, using a relatively lenient adjusted p-value cutoff.
## Get all t-statistics and visualize
res150untag <- .getTestCols(sce150untag, adjp_cutoff = 0.01, logfc_cutoff = 1)
rad <- res150untag$tstat[c("Rad24", "Rad25"), ]
colnames(rad) <- .getProteinNameFromComparison(colnames(rad))
rad <- t(rad)
hmrad <- Heatmap(rad,
cluster_rows = TRUE,
cluster_columns = FALSE,
col = circlize::colorRamp2(
breaks = seq(1.5, 13.0, length.out = 64),
colors = colorRampPalette(
binary_heatmap_colors[c("FALSE", "TRUE")])(64)),
border = TRUE,
border_gp = gpar(lwd = 0.5),
name = "Mod.\nt-stat.",
na_col = binary_heatmap_colors["FALSE"],
column_names_gp = gpar(fontsize = fl),
row_names_gp = gpar(fontsize = fs),
show_row_names = TRUE,
show_column_names = TRUE,
use_raster = FALSE,
show_heatmap_legend = TRUE,
width = unit(w_trad / 1.5, "mm"),
heatmap_height = unit(1.4 * h_trad, "mm"),
column_title_gp = gpar(fontsize = ft),
heatmap_legend_param = list(
title_gp = gpar(fontsize = fl),
border = "gray10",
border_gp = gpar(lwd = 0.5)
))
set.seed(42L)
hm_rad <- grid.grabExpr(
hmrad <- draw(hmrad, merge_legend = TRUE,
heatmap_legend_side = "right",
annotation_legend_side = "right"),
width = w_trad / 1.5, height = 1.4 * h_trad
)
## List of experiments where rad24 and/or rad25 were pulled down
comps <- colnames(res150untag$interactor)[colSums(
res150untag$interactor[c("Rad24", "Rad25"), ], na.rm = TRUE) > 0]
explist <- .getUniProtIdFromComparison(comps, idmap = idmap)
cat(explist)
## Q10280 Q9URT4 P33520 P78926 Q01663 O13658 Q10328 O14283 O59741 Q09838 P41412 P78871 O14335 Q9P7B0 P36631 Q9C0Z1 Q9P7H9 Q10096 Q1MTM9 O94392 O60130 O59744 O74915 O59830
gnames <- .getProteinNameFromComparison(comps)
cat(gnames)
## Gaf1 Ams2 Res1 Map1 Pap1 Pho7 Phx1 Prr1 Prt1 Prz1 Res2 Rst2 Scr1 Stb3 Ste11 Toe3 Dal81 SPAC11D3.17 SPAC1327.01c SPAC2H10.01 Ntu1 Ntu2 SPCC757.04 SPCC965.10
## Read table
set_flextable_defaults(font.size = 8)
rad24_rad25_tbl <- read.delim(params$rad24_rad25_tbl)[, 1:2] |>
setNames(c("TF", "R-x-x-[S/T]-x-P")) |>
dplyr::mutate(TF = .capitalize(TF))
stopifnot(all(gnames %in% rad24_rad25_tbl$TF))
ftbl <- flextable(rad24_rad25_tbl) |>
width(width = c(0.5, 1.25)) |>
set_table_properties(layout = "fixed")
ggtbl <- ggplot() +
theme_void() +
annotation_custom(grid::rasterGrob(as_raster(ftbl)),
xmin = -Inf, xmax = Inf, ymin = 0, ymax = 1)
data.frame(`Number of TFs interacting with at least one 14-3-3 protein` =
nrow(rad24_rad25_tbl),
`Number of such TFs with at least one optimal 14-3-3 binding motif` =
sum(rad24_rad25_tbl$`R-x-x-[S/T]-x-P` != ""),
check.names = FALSE) |>
pivot_longer(cols = everything()) |>
kbl(col.names = NULL) |>
kable_styling()
| Number of TFs interacting with at least one 14-3-3 protein | 24 |
| Number of such TFs with at least one optimal 14-3-3 binding motif | 10 |
# UpSet plot
dfupset <- as.data.frame(t(res150untag$interactor[c("Rad24", "Rad25"), ])) |>
tibble::rownames_to_column("TF") |>
dplyr::mutate(TF = .getProteinNameFromComparison(TF))
ovL <- as.list(as.data.frame(dfupset[, c("Rad24", "Rad25")]))
ovL <- lapply(ovL, function(i) dfupset$TF[which(i)])
pd <- stack(ovL) |>
group_by(values) |>
summarise(ind = list(ind)) |>
dplyr::left_join(rad24_rad25_tbl, by = join_by("values" == "TF")) |>
dplyr::mutate(has_motif = !is.na(`R-x-x-[S/T]-x-P`) & `R-x-x-[S/T]-x-P` != "")
ggrad_upset <- ggplot(pd, aes(x = ind)) +
geom_bar(aes(fill = has_motif)) +
scale_fill_manual(values = c(`TRUE` = main_colors[3], `FALSE` = main_colors[5])) +
scale_x_upset() +
labs(x = element_blank(), y = "Number of IPs", fill = "Has motif: ") +
theme_cowplot(12) +
theme(axis.ticks.x = element_blank(),
legend.position = "bottom") +
theme_combmatrix(combmatrix.label.extra_spacing = 5,
combmatrix.label.make_space = TRUE,
combmatrix.label.width = unit(18, "mm")) +
guides(fill = guide_legend(nrow = 1))
md <- metadata(sce500)
volc <- md$testres$tests$Pho7_500_plate_vs_compl_Pho7_500_plate |>
mutate(signif = adj.P.Val < adjpThreshold & logFC > log2fcThreshold)
(pho7volc <- ggplot(volc, aes(x = logFC, y = mlog10p)) +
geom_text_repel(data = volc |> filter(signif),
aes(label = pid), min.segment.length = 0,
max.overlaps = Inf) +
geom_point(aes(alpha = signif, color = signif),
show.legend = c(alpha = FALSE, color = TRUE)) +
scale_color_manual(values = c(`TRUE` = main_colors[5], `FALSE` = na_color),
labels = c(`TRUE` = paste0("adj. p < ", adjpThreshold,
" and logFC > ", log2fcThreshold)),
na.value = "black", breaks = "TRUE") +
scale_alpha_manual(values = c(`TRUE` = 1, `FALSE` = 0.5)) +
geom_point(data = volc |> dplyr::filter(pid == "Pho7") |>
dplyr::mutate(type = "Bait"),
mapping = aes(fill = type), color = main_colors[3],
shape = 21, alpha = 1, size = 2) +
scale_fill_manual(values = c(Bait = main_colors[3])) +
labs(x = "log2(fold-change)", y = "-log10(p-value)",
title = "Pho7 vs complement (500 mM NaCl IP-MS)") +
theme_cowplot(ft) +
theme(legend.position = "bottom") +
guides(color = guide_legend(nrow = 1, byrow = TRUE, title = ""),
fill = guide_legend(nrow = 1, byrow = TRUE, title = "")))
## Warning: Removed 828 rows containing missing values or values outside the scale
## range (`geom_point()`).
## Create small example similarity matrix and graph, for three selected proteins
poi <- c("Atf1", "Pcr1", "Arp8")
simil150example <- simsFromResults(sce150[poi, ])
gr150example <- createNetwork(similList = simil150example, threshold = 6,
known_interactors = interactors,
settings = "igraph")
## General formula
## See https://uliniemann.com/blog/2022-02-21-math-annotations-in-ggplot2-with-latex2exp/
eqn1 <- data.frame(x = 0, y = 0,
label = r"( $sim_{ik} = min\left(\frac{\sum_{j=1}^N\tilde{t}_{ij}\tilde{t}_{kj}}{\sum_{j=1}^N\tilde{t}_{ij}},\frac{\sum_{j=1}^N\tilde{t}_{ij}\tilde{t}_{kj}}{\sum_{j=1}^N\tilde{t}_{kj}}\right)$ )")
ggeqn1 <- ggplot(eqn1) +
geom_text(aes(x = x, y = y,
label = TeX(label, output = "character"),
color = label),
parse = TRUE,
key_glyph = draw_key_blank,
size = 16/.pt) +
scale_x_continuous(expand = c(0, 0)) +
scale_y_reverse(expand = c(0, 0)) +
scale_color_manual(values = "transparent", labels = TeX(eqn1$label,
italic = TRUE),
name = "") +
guides(color = guide_legend(label.position = "top")) +
theme_void() +
theme(legend.text = element_text(size = 11))
## Specific example (atf1, pcr1)
eqn2 <- data.frame(x = 0, y = 0,
label = r"( $sim_{Atf1,Pcr1} = min\left(\frac{3 \cdot 2.3 + 2.4 \cdot 2.5 + 12.2 \cdot 7.2 + 8.4 \cdot 6.9}{2.3 + 2.5 + 7.2 + 6.9},\frac{3 \cdot 2.3 + 2.4 \cdot 2.5 + 12.2 \cdot 7.2 + 8.4 \cdot 6.9}{3 + 2.4 + 12.2 + 8.4}\right) = min\left(8.4, 6.1\right) = 6.1$ )")
# eqn2 <- data.frame(x = 0, y = 0,
# label = r"( $sim_{\textrm{Atf1,Pcr1}} = \min\left(\frac{3 \cdot 2.3 + 2.4 \cdot 2.5 + 12.2 \cdot 7.2 + 8.4 \cdot 6.9}{2.3 + 2.5 + 7.2 + 6.9},\frac{3 \cdot 2.3 + 2.4 \cdot 2.5 + 12.2 \cdot 7.2 + 8.4 \cdot 6.9}{3 + 2.4 + 12.2 + 8.4}\right) = min\left(8.4, 6.1\right) = 6.1$ )")
ggeqn2 <- ggplot(eqn2) +
geom_text(aes(x = x, y = y,
label = TeX(label, output = "character")),
parse = TRUE,
size = 11/.pt) +
scale_x_continuous(expand = c(0, 0)) +
scale_y_reverse(expand = c(0, 0)) +
theme_void()
## Truncated t-statistics
tstats_vis <- data.frame(simil150example$tstats) |>
tibble::rownames_to_column("Protein") |>
tidyr::pivot_longer(names_to = "IP", values_to = "Value", -Protein) |>
dplyr::mutate(Protein = factor(Protein, levels = poi))
## Reorder IPs for better visualization
enr <- unique(tstats_vis$IP[tstats_vis$Value > 0])
notenr <- setdiff(tstats_vis$IP, enr)
allips <- c(notenr, enr)
intlen <- round(length(notenr) / (length(enr) + 1))
idx <- seq(from = intlen, by = intlen, length.out = length(enr))
levs <- allips[order(c(seq_along(notenr), idx + 0.5))]
tstats_vis$IP <- factor(tstats_vis$IP, levels = levs)
## Plot truncated tstats across all IPs and label relevant points
labels <- tstats_vis |>
dplyr::filter(Value > 0) |>
dplyr::pull(IP) |>
unique()
tplot <- ggplot(tstats_vis, aes(x = IP, y = Value, color = Protein, fill = Protein)) +
geom_col() +
geom_text(
aes(label = ifelse(IP %in% labels & Value > 0, round(Value, digits = 1), "")),
fontface ="plain", color = "black", size = 2.5, nudge_y = 2) +
scale_color_manual(values = c(main_colors[1], main_colors[5], "black")) +
scale_fill_manual(values = c(main_colors[1], main_colors[5], "black")) +
scale_y_continuous(expand = c(0, 1)) +
facet_wrap(~ Protein, ncol = 1) +
labs(x = "IP", y = "Thresholded mod. t-stat.") +
theme_cowplot(font_size = 10) +
theme(legend.position = "none",
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
strip.background = element_rect(fill = NA, colour = NA),
strip.text = element_text(hjust = 0, size = 10, face = "bold"))
## Similarity matrix
similsub <- simil150example$simil[poi, poi] |>
as.data.frame() |>
tibble::rownames_to_column("row") |>
tidyr::pivot_longer(names_to = "column", values_to = "Similarity", -row) |>
dplyr::mutate(Similarity = round(Similarity, digits = 1),
row = factor(row, levels = rev(poi)),
column = factor(column, levels = poi)) |>
dplyr::mutate(simlab = ifelse(Similarity == 0, "", Similarity)) |>
dplyr::mutate(Similarity = ifelse(Similarity == 0, NA, Similarity))
similplot <- ggplot(similsub, aes(x = column, y = row, fill = Similarity)) +
geom_tile() +
geom_text(aes(label = simlab, color = Similarity > 4),
fontface = "bold") +
scale_color_manual(values = c(`TRUE` = "white", `FALSE` = "black")) +
scale_fill_gradient(low = "white", high = binary_heatmap_colors["TRUE"],
na.value = na_color,
limits = range(similsub$Similarity, na.rm = TRUE)) +
theme_cowplot() +
theme(axis.line = element_blank(),
axis.ticks = element_blank(),
legend.position = "bottom",
legend.title = element_text(size = 10, vjust = 0.82),
legend.margin = margin(0, 0, 0, 0),
legend.box.spacing = unit(0, "pt")) +
labs(x = "", y = "") +
guides(color = "none")
## Induced graph
ggr150example <- ggraph(as_tbl_graph(gr150example),
layout = cbind(x = c(-300, 800), y = c(800, -300)),
weights = weight) +
geom_edge_link(aes(color = edgeclass, width = weight)) +
scale_edge_color_manual(values = c(`Unannotated TF interaction` = main_colors[3],
Other = gplots::col2hex(na_color)),
name = "") +
scale_edge_width(range = c(1.2, 1.9), guide = "none") +
geom_node_point(size = 4, aes(fill = vertexclass, shape = vertexclass),
color = "black", stroke = 0.1) +
scale_shape_manual(values = c(other = 21, Bait = 22), name = "") +
scale_fill_manual(values = c(other = gplots::col2hex(bg_color), Bait = main_colors[5]),
name = "") +
geom_node_text(aes(label = name), size = 3.5, repel = TRUE,
nudge_x = 0, nudge_y = -5) +
theme_graph(base_family = "sans", plot_margin = margin(30, 10, 40, 10)) +
guides(fill = guide_legend(override.aes = list(size = 4, alpha = 1))) +
coord_cartesian(clip = "off")
## Put together
figs6c <- cowplot::plot_grid(
cowplot::plot_grid(
tplot,
get_legend(ggeqn1, "right"),
similplot + theme(legend.position = "bottom"),
ggr150example + theme(legend.position = "none"),
align = "v", axis = "t",
labels = c("C", "", "", ""), nrow = 1, vjust = -0.5,
rel_widths = c(1.1, 0.9, 1, 0.5)
),
ggeqn2, ncol = 1, labels = "",
rel_heights = c(3, 1)
)
fig6b <- ggdraw() +
draw_image("schematics/Fig6B_Pho7_protein_domains_cartoon_Arial_RGB.png")
coords150 <- read.csv(params$coords150)
coords500 <- read.csv(params$coords500)
coords150$y <- -coords150$y
coords500$y <- -coords500$y
.plotGraph <- function(grph, coords, nudge_y) {
ggraph(as_tbl_graph(grph),
layout = coords,
weights = weight) +
geom_edge_link(aes(color = edgeclass, width = weight)) +
scale_edge_color_manual(values = c(`Unannotated TF interaction` = main_colors[3],
Other = gplots::col2hex(na_color)),
breaks = "Unannotated TF interaction",
name = "") +
scale_edge_width(range = c(0.2, 0.9), guide = "none") +
geom_node_point(size = 2, aes(fill = vertexclass, shape = vertexclass),
color = "black", stroke = 0.1) +
scale_shape_manual(values = c(other = 21, Bait = 22), name = "",
breaks = "Bait") +
scale_fill_manual(values = c(other = gplots::col2hex(bg_color), Bait = main_colors[5]),
name = "", breaks = "Bait") +
geom_node_text(aes(label = name), size = 2.5, repel = FALSE,
nudge_x = 0, nudge_y = nudge_y) +
theme_graph(base_family = "sans", plot_margin = margin(10, 10, 10, 10)) +
guides(fill = guide_legend(override.aes = list(size = 4, alpha = 1)))
}
ggr150 <- .plotGraph(grph = gr150, coords = as.matrix(coords150[, c("x", "y")]),
nudge_y = -45)
ggr500 <- .plotGraph(grph = gr500, coords = as.matrix(coords500[, c("x", "y")]),
nudge_y = -35)
cowplot::plot_grid(
cowplot::plot_grid(
pho7volc,
cowplot::plot_grid(
cowplot::plot_grid(NULL, fig6b, NULL, nrow = 1,
rel_widths = c(0.25, 1, 0.1)),
ggrad_upset,
ncol = 1, labels = c("B", "C"),
rel_heights = c(1, 1.75)),
nrow = 1, labels = c("A", "")
),
NULL,
cowplot::plot_grid(
cowplot::plot_grid(
ggr150 + theme(legend.position = "none") +
ggtitle("150 mM NaCl IP-MS") +
theme(plot.title = element_text(hjust = 0.075, size = ft)),
ggr500 + theme(legend.position = "none") +
ggtitle("500 mM NaCl IP-MS") +
theme(plot.title = element_text(hjust = 0.075, size = ft)),
nrow = 1, labels = c("D", "E"), vjust = 1.8
),
get_legend(ggr150 + theme(legend.position = "bottom"), "bottom"),
nrow = 2, labels = c("", ""), rel_heights = c(1, 0.1)
),
rel_heights = c(3.5, 0.3, 4.25),
ncol = 1
)
We extract all IPs where either Rad24 or Rad25 are pulled down, using a relatively lenient adjusted p-value cutoff.
plot_grid(
plot_grid(hm_rad, ggtbl, nrow = 1, align = "h", axis = "b",
rel_widths = c(2, 2.5), labels = c("A", "B")),
figs6c,
rel_heights = c(3, 1), ncol = 1,
labels = c("", "")
)
sessionInfo()
## R version 4.3.2 (2023-10-31)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: CentOS Linux 7 (Core)
##
## Matrix products: default
## BLAS/LAPACK: FlexiBLAS OPENBLAS; LAPACK version 3.10.1
##
## 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: Europe/Zurich
## tzcode source: system (glibc)
##
## attached base packages:
## [1] grid stats4 stats graphics grDevices utils datasets
## [8] methods base
##
## other attached packages:
## [1] jsonlite_1.8.8 tidyr_1.3.1
## [3] ggupset_0.3.0 kableExtra_1.4.0
## [5] flextable_0.9.5 ComplexHeatmap_2.18.0
## [7] ggrepel_0.9.5 tidygraph_1.3.1
## [9] latex2exp_0.9.6 ggraph_2.2.1
## [11] ggplotify_0.1.2 cowplot_1.1.3
## [13] shiny_1.8.1.1 igraph_2.0.3
## [15] ggplot2_3.5.0 dplyr_1.1.4
## [17] SingleCellExperiment_1.24.0 SummarizedExperiment_1.32.0
## [19] Biobase_2.62.0 GenomicRanges_1.54.1
## [21] GenomeInfoDb_1.38.8 IRanges_2.36.0
## [23] S4Vectors_0.40.2 BiocGenerics_0.48.1
## [25] MatrixGenerics_1.14.0 matrixStats_1.3.0
## [27] visNetwork_2.1.2
##
## loaded via a namespace (and not attached):
## [1] RColorBrewer_1.1-3 rstudioapi_0.16.0 shape_1.4.6.1
## [4] magrittr_2.0.3 magick_2.8.3 farver_2.1.1
## [7] rmarkdown_2.26 GlobalOptions_0.1.2 fs_1.6.3
## [10] zlibbioc_1.48.2 ragg_1.3.0 vctrs_0.6.5
## [13] Cairo_1.6-2 memoise_2.0.1 RCurl_1.98-1.14
## [16] askpass_1.2.0 htmltools_0.5.8.1 S4Arrays_1.2.1
## [19] curl_5.2.1 SparseArray_1.2.4 gridGraphics_0.5-1
## [22] sass_0.4.9 KernSmooth_2.23-22 bslib_0.7.0
## [25] htmlwidgets_1.6.4 cachem_1.0.8 uuid_1.2-0
## [28] mime_0.12 lifecycle_1.0.4 iterators_1.0.14
## [31] pkgconfig_2.0.3 Matrix_1.6-5 R6_2.5.1
## [34] fastmap_1.1.1 GenomeInfoDbData_1.2.11 clue_0.3-65
## [37] digest_0.6.35 colorspace_2.1-0 textshaping_0.3.7
## [40] labeling_0.4.3 fansi_1.0.6 polyclip_1.10-6
## [43] abind_1.4-5 compiler_4.3.2 fontquiver_0.2.1
## [46] withr_3.0.0 doParallel_1.0.17 viridis_0.6.5
## [49] highr_0.10 ggforce_0.4.2 gplots_3.1.3.1
## [52] MASS_7.3-60 openssl_2.1.2 DelayedArray_0.28.0
## [55] rjson_0.2.21 gfonts_0.2.0 gtools_3.9.5
## [58] caTools_1.18.2 tools_4.3.2 zip_2.3.1
## [61] httpuv_1.6.15 glue_1.7.0 promises_1.3.0
## [64] cluster_2.1.4 generics_0.1.3 gtable_0.3.5
## [67] data.table_1.15.4 xml2_1.3.6 utf8_1.2.4
## [70] XVector_0.42.0 foreach_1.5.2 pillar_1.9.0
## [73] stringr_1.5.1 yulab.utils_0.1.4 later_1.3.2
## [76] circlize_0.4.16 tweenr_2.0.3 lattice_0.22-6
## [79] tidyselect_1.2.1 fontLiberation_0.1.0 knitr_1.46
## [82] fontBitstreamVera_0.1.1 gridExtra_2.3 svglite_2.1.3
## [85] crul_1.4.2 xfun_0.43 graphlayouts_1.1.1
## [88] stringi_1.8.3 yaml_2.3.8 evaluate_0.23
## [91] codetools_0.2-19 httpcode_0.3.0 officer_0.6.5
## [94] gdtools_0.3.7 tibble_3.2.1 cli_3.6.2
## [97] xtable_1.8-4 systemfonts_1.0.6 munsell_0.5.1
## [100] jquerylib_0.1.4 Rcpp_1.0.12 png_0.1-8
## [103] parallel_4.3.2 bitops_1.0-7 viridisLite_0.4.2
## [106] scales_1.3.0 purrr_1.0.2 crayon_1.5.2
## [109] GetoptLong_1.0.5 rlang_1.1.3