Switch to unified view

a b/figures/SupplementaryFigures.Rmd
1
---
2
title: "Supplementary Figures"
3
author: Tobias Roider
4
date: "Last compiled on `r format(Sys.time(), '%d %B, %Y, %X')`"
5
output: 
6
  rmdformats::readthedown:
7
  
8
editor_options: 
9
  chunk_output_type: console
10
---
11
12
```{r options, include=FALSE, warning = FALSE}
13
14
library(knitr)
15
opts_chunk$set(echo=TRUE, tidy=FALSE, include=TRUE, message=FALSE, cache.lazy = FALSE,
16
               dpi = 100, cache = FALSE, warning = FALSE)
17
opts_knit$set(root.dir = "../")
18
options(bitmapType = "cairo")
19
20
```
21
22
# Read data, functions and packages
23
```{r read data}
24
25
source("R/ReadPackages.R")
26
source("R/Functions.R")
27
source("R/ReadData.R")
28
source("R/ThemesColors.R")
29
source("R/Helpers.R")
30
31
```
32
33
# Supplementary Figure 1
34
## Patient characteristics
35
```{r patient characteristics SF1 part 1}
36
37
p1 <- 
38
  df_meta %>% 
39
  ggplot(aes(x=Order, y=Tcells, fill=Entity))+
40
  geom_bar(stat = "identity", color="white", width=0.5, size=0.25)+
41
  geom_text(aes(x=6, y=84, label=paste0("n = ", nrow(df_meta))), check_overlap = T, size=2.75)+
42
  scale_y_continuous(name="% T-cells", limits=c(0, 90), expand = c(0.025, 0.025))+
43
  scale_x_discrete(limits=as.character(1:101))+
44
  scale_fill_manual(values = colors_characteristics)+
45
  mytheme_1+
46
  coord_cartesian(clip = "off")+
47
  theme(axis.text.x = element_blank(),
48
        axis.title.x = element_blank(),
49
        axis.title.y = element_text(size=7),
50
        axis.ticks.x = element_blank(),
51
        plot.tag = element_text(margin = unit(c(0,0,0,-0.75), "cm")),
52
        plot.margin = unit(c(0.1,0.1,0,1), "lines"))
53
54
cex_ <- 0.6
55
pos_ <- -0.25
56
size_ <- 2.4
57
58
p_ann <- 
59
  ggplot()+
60
  geom_tile(data=df_meta, aes(y=0, x=Order, fill=Entity))+
61
  geom_tile(data=df_meta, aes(y=-1.75, x=Order, fill=Status))+
62
  geom_tile(data=df_meta, aes(y=-3.5, x=Order, fill=Sex))+
63
  geom_text(data=df_meta, aes(y=-5.25, x=Order, label=`CITEseq`), size=size_)+
64
  geom_text(data=df_meta, aes(y=-7, x=Order, label=`TCRseq`), size=size_)+
65
  geom_text(data=df_meta, aes(y=-8.75, x=Order, label=`MultiIF`), size=size_)+
66
  geom_text(data=df_meta, aes(y=-10.5, x=Order, label=`MultiFlow`), size=size_)+
67
  annotation_custom(grob=textGrob(label = "Entity", gp = gpar(cex=cex_), just="right"), xmin = pos_, xmax = pos_, ymin = 0, ymax = 0)+
68
  annotation_custom(grob=textGrob(label = "Collection", gp = gpar(cex=cex_), just="right"), xmin = pos_, xmax = pos_, ymin = -1.75, ymax = -1.75)+
69
  annotation_custom(grob=textGrob(label = "Sex", gp = gpar(cex=cex_), just="right"), xmin = pos_, xmax = pos_, ymin = -3.5, ymax = -3.5)+
70
  annotation_custom(grob=textGrob(label = "CITE-seq", gp = gpar(cex=cex_), just="right"), xmin = pos_, xmax = pos_, ymin = -5.25, ymax = -5.25)+
71
  annotation_custom(grob=textGrob(label = "TCR-seq", gp = gpar(cex=cex_), just="right"), xmin = pos_, xmax = pos_, ymin = -7, ymax = -7)+
72
  annotation_custom(grob=textGrob(label = "Multi-IF", gp = gpar(cex=cex_), just="right"), xmin = pos_, xmax = pos_, ymin = -8.75, ymax = -8.75)+
73
  annotation_custom(grob=textGrob(label = "Multi-flow", gp = gpar(cex=cex_), just="right"), xmin = pos_, xmax = pos_, ymin = -10.5, ymax = -10.5)+
74
   scale_x_discrete(limits=as.character(1:101))+
75
  scale_y_continuous(expand = c(0,0), name=NULL)+
76
  geom_vline(xintercept = seq(0.5, nrow(df_meta), 1), size=1, color="white")+
77
  scale_fill_manual(values = colors_characteristics)+
78
  coord_cartesian(clip = "off")+
79
  theme_void()+
80
  theme(legend.position = "none",
81
        plot.margin = unit(c(0,0.1,0,0.1), "lines"))
82
83
plot_legend1 <- 
84
  ggplot()+
85
  geom_tile(data=df_meta, aes(y=4, x=Order, fill=Entity))+
86
  scale_x_discrete(expand = c(0,0), name=NULL)+
87
  scale_y_discrete(expand = c(0,0), name=NULL)+
88
  geom_vline(xintercept = seq(0.5, 51.5, 1), color="white")+
89
  scale_fill_manual(values = colors_characteristics, limits=df_meta$Entity %>% unique())+
90
  guides(fill=guide_legend(direction = "horizontal", keywidth = 0.3, keyheight = 0.4))+
91
  theme_void()+
92
  mytheme_1+
93
  theme(legend.position = "bottom",
94
        legend.title = element_text(size=7, face = "bold"),
95
        legend.text = element_text(size=7))
96
97
legend1 <- get_legend(plot_legend1)
98
99
plot_legend2 <-
100
  ggplot()+
101
  geom_tile(data=df_meta, aes(y=4, x=Order, fill=Sex))+
102
  scale_x_discrete(expand = c(0,0), name=NULL)+
103
  scale_y_discrete(expand = c(0,0), name=NULL)+
104
  geom_vline(xintercept = seq(0.5, 51.5, 1), color="white")+
105
  scale_fill_manual(values = colors_characteristics, limits=df_meta$Sex %>% unique())+
106
  guides(fill=guide_legend(direction = "horizontal", keywidth = 0.3, keyheight = 0.4))+
107
  theme_void()+
108
  mytheme_1+
109
  theme(legend.position = "bottom",
110
        legend.title = element_text(size=7, face = "bold"),
111
        legend.text = element_text(size=7))
112
113
legend2 <- get_legend(plot_legend2)
114
115
plot_legend3 <- 
116
  ggplot()+
117
  geom_tile(data=df_meta, aes(y=4, x=Order, fill=Status))+
118
  scale_x_discrete(expand = c(0,0), name=NULL)+
119
  scale_y_discrete(expand = c(0,0), name=NULL)+
120
  geom_vline(xintercept = seq(0.5, 51.5, 1), color="white")+
121
  scale_fill_manual(values = colors_characteristics, name="Collection",
122
                    limits=filter(df_meta, Status!="NA")$Status %>% unique())+
123
  guides(fill=guide_legend(direction = "horizontal", keywidth = 0.3, keyheight = 0.4))+
124
  theme_void()+
125
  mytheme_1+
126
  theme(legend.position = "bottom",
127
        legend.title = element_text(size=7, face = "bold"),
128
        legend.text = element_text(size=7))
129
130
legend3 <- get_legend(plot_legend3)
131
132
```
133
134
## Associations with overall T-cell frequencies
135
```{r patient characteristics SF1 part 2}
136
137
# Sex
138
p2 <- df_meta %>% 
139
  filter(!Entity %in% c("CLL", "rLN")) %>%
140
  mutate(Tcells=ifelse(is.na(Tcells), TcellsDx, Tcells)) %>% 
141
  filter(Tcells>1) %>% 
142
  ggplot(aes(x=Sex, y=Tcells))+
143
  geom_boxplot(width=0.35, size=0.25)+
144
  #ggbeeswarm::geom_beeswarm(size=0.8, shape=21, stroke=0.25, cex = 2.75, aes(fill=Entity))+
145
  stat_compare_means(comparisons = list(c("F", "M")), label.y = 78, size=2.5, bracket.size = 0.25)+
146
  scale_fill_manual(values = hue_pal()(5))+
147
  scale_x_discrete(labels=c("Female", "Male"))+
148
  ylim(0,90)+
149
  ylab("T-cells in %")+
150
  mytheme_1+
151
  theme(axis.title.x = element_blank(),
152
        plot.tag = element_text(margin = unit(c(0,0,0,-0.75), "cm")))+
153
  labs(tag = "B")
154
155
# Status
156
p3 <- df_meta %>% 
157
  filter(!Entity %in% c("CLL", "rLN")) %>%
158
  mutate(Tcells=ifelse(is.na(Tcells), TcellsDx, Tcells)) %>% 
159
  filter(Tcells>1) %>% 
160
  ggplot(aes(x=Status, y=Tcells))+
161
  geom_boxplot(width=0.35, size=0.25)+
162
  #ggbeeswarm::geom_beeswarm(size=0.8, shape=21, stroke=0.25, cex = 2.75, aes(fill=Entity))+
163
  stat_compare_means(comparisons = list(c("Initial diagnosis", "Relapse")), label.y = 78, bracket.size = 0.25, size=2.5)+
164
  scale_x_discrete(labels=c("Initial \ndiagnosis", "Relapse"))+
165
  scale_fill_manual(values = hue_pal()(5))+
166
  ylim(0,90)+
167
  ylab("T-cells in %")+
168
  mytheme_1+
169
  theme(axis.title.x = element_blank())+
170
  labs(tag = "C")
171
172
# Age
173
p5 <- df_meta %>% 
174
  filter(!Entity %in% c("CLL", "rLN")) %>%
175
  mutate(Tcells=ifelse(is.na(Tcells), TcellsDx, Tcells)) %>% 
176
  filter(Tcells>1) %>% 
177
  ggplot(aes(x=Age, y=Tcells))+
178
  geom_point(size=1.25, shape=21, stroke=0.25, color="white", aes(fill=Entity))+
179
  stat_cor(aes(label=..r.label..),  size=2.5, label.y = 82)+
180
  scale_fill_manual(values = colors_characteristics, name=NULL, limits=c("DLBCL", "FL", "MCL", "MZL"))+
181
  ylim(0,90)+
182
  ylab("T-cells in %")+
183
  mytheme_1+
184
  theme(legend.position = "right",
185
        axis.title.x = element_text(vjust = 6.5),
186
        legend.box.margin = unit(c(0,0,0,-0.38), "cm"),
187
        legend.key.width = unit("cm", x = 0.15),
188
        legend.key.height = unit("cm", x = 0.35))+
189
  labs(tag = "D")
190
191
# Entity
192
df_tmp <- df_meta %>% 
193
  filter(!Entity %in% c("CLL", "rLN")) %>%
194
  mutate(Tcells=ifelse(is.na(Tcells), TcellsDx, Tcells)) %>% 
195
  filter(Tcells>1)
196
  
197
p6 <- ggplot(df_meta, aes(x=Entity, y=Tcells))+
198
  geom_boxplot(width=0.4, size=0.25)+
199
  ggbeeswarm::geom_beeswarm(size=0.75, shape=21, stroke=0.25, cex = 2.25, aes(fill=Entity))+
200
  stat_compare_means(data=df_tmp %>% filter(!Entity %in% c("rLN")), 
201
                     label.y = 83, label.x = 2.5, size=2.5, hjust=0.5, bracket.size = 0.25)+
202
  scale_fill_manual(values = colors_characteristics, name=NULL, 
203
                    limits=c("DLBCL", "FL", "MCL", "MZL", "rLN"))+
204
  geom_segment(data = NULL, aes(x=1, xend=4, y=80, yend=80), size=0.1)+
205
  ylim(0,90)+
206
  ylab("T-cells in %")+
207
  mytheme_1+
208
  theme(axis.title.x = element_blank())+
209
  labs(tag = "E")
210
211
```
212
213
## Assemble plot
214
```{r assemble SF1, fig.height=5.5}
215
216
# Plot
217
wrap_plots(p1+labs(tag = "A")+p_ann+plot_layout(nrow = 2, heights = c(1, 0.5)))/
218
  plot_spacer()/
219
  wrap_plots(p2+p3+p5+p6+plot_layout(nrow = 1, widths = c(0.55,0.55,1,1)))+
220
  plot_layout(heights = c(1.25,0.075,0.7))
221
222
#ggsave(width = 18.5, height = 12, units = "cm", filename = "SF1.pdf")
223
224
```
225
226
## Legend
227
```{r legend SF1, fig.height=0.5}
228
229
# Legend
230
as_ggplot(legend1)+as_ggplot(legend2)+as_ggplot(legend3)+plot_layout(nrow = 1, widths = c(1, 0.5, 0.75))
231
ggsave(width = 13, height = 1, units = "cm", filename = "S1_p1_legend.pdf")
232
233
```
234
235
# Supplementary Figure 2
236
## Confusion Matrix
237
```{r, confusion SF2, fig.height=4.5}
238
239
confmat <- confusionMatrix(GBclasses_surface$test, GBclasses_surface$predict)
240
241
conf_freq <- confmat$table %>% 
242
  data.frame() %>% 
243
  group_by(Reference) %>% 
244
  mutate(Prop=Freq/sum(Freq)) 
245
  
246
plot_surface <- ggplot(conf_freq, aes(x=Reference, y=Prediction, fill=Prop, label=round(Prop, 2)))+
247
  geom_tile()+
248
  geom_text(data=conf_freq %>% filter(Prop>0.4), color="white", size=1.75)+
249
    scale_fill_gradientn(colours = colorRampPalette(RColorBrewer::brewer.pal(9, "BuPu"))(100), name="Sensitivity",
250
                       limits=c(0,0.9), breaks=seq(0,0.8,0.2))+
251
  geom_hline(yintercept = seq(1.5, 13.5), color="black",linetype="solid", size=0.25, alpha=0.25)+
252
  geom_vline(xintercept = seq(1.5, 13.5), color="black",linetype="solid", size=0.25, alpha=0.25)+
253
  scale_y_discrete(expand = c(0,0), limits=factor(cluster_order), labels=unlist(labels_cl))+
254
  scale_x_discrete(expand = c(0,0), limits=factor(cluster_order), labels=unlist(labels_cl))+
255
  coord_fixed()+
256
  ggtitle("Surface marker only")+
257
  mytheme_1+
258
  theme(legend.position = "none",
259
        axis.text.x = element_text(angle=45, hjust = 1))+
260
  labs(tag = "A")
261
262
confmat_plus <- confusionMatrix(GBclasses_surfaceplus$test, GBclasses_surfaceplus$predict)
263
264
conf_freq <- confmat_plus$table %>% 
265
  data.frame() %>% 
266
  group_by(Reference) %>% 
267
  mutate(Prop=Freq/sum(Freq)) 
268
  
269
plot_surfaceplus <- ggplot(conf_freq, aes(x=Reference, y=Prediction, fill=Prop, label=round(Prop, 2)))+
270
  geom_tile()+
271
  geom_text(data=conf_freq %>% filter(Prop>0.4), color="white", size=1.75)+
272
  scale_fill_gradientn(colours = colorRampPalette(RColorBrewer::brewer.pal(9, "BuPu"))(100), name="Sensitivity",
273
                       limits=c(0,0.9), breaks=seq(0,0.8,0.2))+
274
  geom_hline(yintercept = seq(1.5, 13.5), color="black",linetype="solid", size=0.25, alpha=0.25)+
275
  geom_vline(xintercept = seq(1.5, 13.5), color="black",linetype="solid", size=0.25, alpha=0.25)+
276
  scale_y_discrete(expand = c(0,0), limits=factor(cluster_order), labels=unlist(labels_cl))+
277
  scale_x_discrete(expand = c(0,0), limits=factor(cluster_order), labels=unlist(labels_cl))+
278
  coord_fixed()+
279
  ggtitle("Surface plus FoxP3, IKZF3, and Ki67")+
280
  mytheme_1+
281
  theme(legend.position = "right",
282
        legend.key.height = unit(0.35, "cm"),
283
        legend.key.width = unit(0.28, "cm"),
284
        legend.margin = margin(c(0,0.2,0,0), unit = "cm"),
285
        axis.text.x = element_text(angle=45, hjust = 1))+
286
  labs(tag = "B")
287
288
plot_surface+plot_surfaceplus+plot_layout(guides = "collect", widths = c(1,1))
289
290
#ggsave(width = 19, height = 9, units = "cm", filename = "SF2.pdf")
291
292
```
293
294
# Supplementary Figure 3
295
## Frequencies overview
296
```{r freq overview SF3}
297
298
df_pop
299
300
mat_complete <- rbind(
301
  df_facs %>% 
302
    left_join(., df_meta %>% select(PatientID, `CITEseq`)) %>% 
303
    filter(`CITEseq`=="-") %>% 
304
    select(PatientID, Population, Prop=FACS),
305
  df_freq %>% 
306
    mutate(RNA=ifelse(is.nan(RNA), 0, RNA)) %>% 
307
    select(PatientID, Population, Prop=RNA)) %>% 
308
  filter(Population %in% df_pop$Population) %>% 
309
  left_join(., df_pop) %>% 
310
  select(-Population) %>% 
311
  left_join(., df_meta %>% select(PatientID, Tcells)) %>% 
312
  mutate(Prop=Tcells*Prop/100) %>% 
313
  select(-Tcells) %>% 
314
  pivot_wider(names_from = "IdentI", values_from = "Prop", values_fill = 0) %>% 
315
  column_to_rownames("PatientID") 
316
317
cl_order <- c(6,1,2,9,8,13,15,11,12,16,3,5,14,19)
318
names(labels_cl_parsed) <- as.character(cluster_order)
319
320
df_freqPlot <- 
321
  mat_complete %>% 
322
  rownames_to_column("PatientID") %>% 
323
  pivot_longer(cols=2:ncol(.), names_to = "IdentI", values_to = "Prop") %>% 
324
  add_entity() %>% 
325
  mutate(Entity=factor(Entity, levels = c("rLN", "DLBCL", "MCL", "FL", "MZL"))) %>% 
326
  mutate(IdentI=factor(IdentI, levels=cl_order)) %>% 
327
  mutate(Label=factor(IdentI, levels=cl_order, labels = labels_cl_parsed[as.character(cl_order)])) %>% 
328
  group_by(Entity, IdentI) %>% 
329
  mutate(outlier = (Prop > quantile(Prop, 0.75) + IQR(Prop) * 1.5) | (Prop < quantile(Prop, 0.25) - IQR(Prop) * 1.5))
330
331
df_medianLines <- df_freqPlot %>% 
332
  filter(Entity=="rLN") %>% 
333
  group_by(IdentI, Label) %>% 
334
  summarise(MedianProp=median(Prop))
335
336
df_freqPlot_pvalues <- df_freqPlot %>% 
337
  group_by(IdentI) %>% 
338
  wilcox_test(data=., formula = Prop ~ Entity, detailed = T, ref.group = "rLN") %>% 
339
  adjust_pvalue(method = "BH") %>% 
340
  select(IdentI, Entity=group2, p.adj, estimate) %>% 
341
  mutate(Entity=factor(Entity, levels = c("rLN", "DLBCL", "MCL", "FL", "MZL"))) %>% 
342
  mutate(p.adj=ifelse(p.adj>0.05, NA, p.adj)) %>% 
343
  mutate(p.adj_s=format(p.adj, scientific = TRUE, digits=1)) %>% 
344
  mutate(p.adj_f=case_when(p.adj > 0.05 ~ "NA",
345
                           p.adj==0.05 ~ "0.05",
346
                           p.adj < 0.05 & p.adj > 0.001 ~ as.character(round(p.adj, 3)),
347
                           p.adj==0.001 ~ "0.001",
348
                           p.adj < 0.001 ~ p.adj_s)) %>% 
349
  filter(!is.na(p.adj)) %>% 
350
  left_join(., df_freqPlot %>% select(IdentI,  Label) %>% distinct) %>% 
351
  left_join(., data.frame(IdentI=factor(cl_order), height=c(28, 28, 21, 21, 10, 10, 12, 12, 14, 14, 50, 50, 12, 12)))
352
353
```
354
355
## Plot
356
```{r freq overview, fig.height=6, fig.width=5.2}
357
358
p <- list()
359
360
for(i in c(1:7)){
361
  
362
  y <- list(c(1,6),c(2,9),c(8,13),c(15,11),c(12,16),c(3,5),c(14,19))[[i]]
363
  ylim <- c(38,30,13,15.5,20,65,15)
364
  
365
  p[[i]] <- 
366
    ggplot(data=df_freqPlot %>% filter(IdentI %in% y) %>% 
367
             mutate(Label=factor(Label, levels = labels_cl_parsed[as.character(y)])), 
368
             aes(y=Prop, x=Entity, fill=IdentI))+
369
    geom_hline(data=df_medianLines %>%filter(IdentI %in% y), aes(yintercept=MedianProp),
370
               size=0.25, linetype="dashed", color="grey60")+
371
    geom_boxplot(width=0.4, outlier.shape = 21, outlier.size = 1, outlier.color = "white", 
372
                 outlier.alpha = 0, show.legend = F, size=0.25)+
373
    ggbeeswarm::geom_beeswarm(data = function(x) dplyr::filter_(x, ~ outlier), cex = 3, stroke=0.25, 
374
                              groupOnX = TRUE, shape = 21, size = 1, color = "white", alpha = 1)+
375
    geom_text(data=df_freqPlot_pvalues %>% filter(IdentI %in% y), 
376
              inherit.aes = F, aes(y=height, x=Entity, label=p.adj_f), hjust=0.1, size=2.3, angle=45)+
377
    scale_fill_manual(values = colors_umap_cl)+
378
    scale_y_continuous(name="% of total cells", limits=c(0,ylim[i]))+
379
    scale_x_discrete(expand = c(0.17,0.17))+
380
    facet_wrap(~Label, ncol = 2, labeller = label_parsed)+
381
    mytheme_1+
382
    theme(axis.title.x = element_blank(),
383
          strip.background = element_rect(color=NA),
384
          plot.margin = unit(c(0.1,0.25,0,0), units = "cm"),
385
          panel.border = element_rect(size = 0.5),
386
          axis.text.x = element_text(angle=45, hjust = 1))
387
  
388
  if(i!=7){
389
    p[[i]] <- p[[i]]+
390
      theme(axis.text.x = element_blank(),
391
            axis.ticks.x = element_blank())
392
  }
393
  
394
  if(!i %in% c(4,5)){
395
    p[[i]] <- p[[i]]+
396
      theme(axis.title.y = element_blank())
397
    }
398
  
399
}
400
401
plot_freq <- wrap_plots(p, ncol = 2)
402
plot_freq
403
ggsave(width = 18.5, height = 15, units = "cm", filename = "SF3.pdf")
404
405
```
406
407
408
# Supplementary Figure 4
409
## Lasso model (beta coefficients)
410
```{r lasso model SF4}
411
412
mat_complete <- rbind(
413
  df_facs %>% 
414
    left_join(., df_meta %>% select(PatientID, `CITEseq`)) %>% 
415
    filter(`CITEseq`=="-") %>% 
416
    select(PatientID, Population, Prop=FACS),
417
  df_freq %>% 
418
    mutate(RNA=ifelse(is.nan(RNA), 0, RNA)) %>% 
419
    select(PatientID, Population, Prop=RNA)) %>% 
420
  filter(Population %in% df_pop$Population) %>% 
421
  left_join(., df_pop) %>% 
422
  select(-Population) %>% 
423
  pivot_wider(names_from = "IdentI", values_from = "Prop", values_fill = 0) %>% 
424
  column_to_rownames("PatientID") 
425
426
total <- mat_complete %>% 
427
  rownames_to_column("PatientID") %>% 
428
  left_join(., df_meta %>% select(PatientID, Tcells)) %>% 
429
  add_entity() %>% 
430
  mutate_if(is.numeric, .funs = ~./100)
431
432
cell_types <- total %>% select(-Entity, -PatientID) %>% colnames()
433
434
gt <- my_glmnet(total)
435
436
limits_coefs=c(cluster_order, "Tcells", "(Intercept)")
437
438
plot_coefs <- gt$coefs %>% 
439
  mutate(Entity=factor(Entity, levels = c("rLN", "DLBCL", "MCL", "FL", "MZL"))) %>% 
440
  ggplot(aes(x=beta, y=cell_type,  fill=cell_type, color=cell_type))+
441
  geom_hline(yintercept = c(1.5, 5.5, 9.5, 10.5, 13.5)+2, linetype="solid", size=0.25, alpha=0.1)+
442
  geom_bar(stat = "identity", width = 0.5)+
443
  scale_y_discrete(limits=rev(limits_coefs), labels=c("Intercept", "T cells", rev(unlist(unname(labels_cl)))))+
444
  scale_color_manual(limits=rev(limits_coefs), values = c("black", "black", rev(unname(colors_umap_cl[as.character(cluster_order)]))))+
445
  scale_fill_manual(limits=rev(limits_coefs), values = c("black", "black", rev(unname(colors_umap_cl[as.character(cluster_order)]))))+
446
  facet_wrap(~Entity, ncol=5)+
447
  mytheme_1+
448
  theme(axis.title.y = element_blank(),
449
        panel.border = element_rect(size = 0.5))
450
451
```
452
453
## Multivariate Model
454
```{r multivariate model SF4, fig.height=7}
455
456
models <- list()
457
entities <- c("Overall", "FL", "MZL", "MCL")
458
459
for(i in colnames(mat_complete)){
460
  for(e in entities) {
461
  ent <- e
462
  if(e=="Overall"){ent <- c("FL", "MZL", "MCL", "DLBCL")}
463
    
464
models[[paste0(i, "_", e)]] <- mat_complete %>% 
465
  rownames_to_column("PatientID") %>% 
466
  pivot_longer(cols=2:ncol(.), names_to = "IdentI", values_to = "Prop") %>% 
467
  left_join(., df_meta %>% select(PatientID, Status, Pretreatment, Sex, Entity, Department, Age, Subtype, Tcells, `CITEseq`) %>% distinct, 
468
            by="PatientID") %>%
469
  filter(Entity %in% ent) %>% 
470
  filter(IdentI==i) %>% 
471
  glm(formula = Prop ~ Status + Age + Sex, 
472
      family = "gaussian") %>% summary()
473
474
models[[paste0(i, "_", e)]] <- models[[paste0(i, "_", e)]]$coefficients %>% 
475
  `colnames<-`(c("Estimate", "Std.error", "t.value", "p.value")) %>% 
476
  data.frame() %>% 
477
  dplyr::mutate(IdentI=as.character(i)) %>% 
478
  rownames_to_column("Parameter")
479
480
}
481
}
482
483
for(i in colnames(mat_complete)){
484
  ent <- "DLBCL"
485
  e <- "DLBCL"
486
  models[[paste0(i, "_", e)]] <- mat_complete %>% 
487
    rownames_to_column("PatientID") %>% 
488
    pivot_longer(cols=2:ncol(.), names_to = "IdentI", values_to = "Prop") %>% 
489
    left_join(., df_meta %>% select(PatientID, Status, Pretreatment, Sex, Entity, Department, Age, Subtype, Tcells, `CITEseq`) %>% distinct, 
490
              by="PatientID") %>%
491
    filter(Entity %in% ent) %>% 
492
    filter(IdentI==i) %>% 
493
    glm(formula = Prop ~ Status + Age + Sex + Subtype, 
494
        family = "gaussian") %>% summary()
495
496
models[[paste0(i, "_", e)]] <- models[[paste0(i, "_", e)]]$coefficients %>% 
497
  `colnames<-`(c("Estimate", "Std.error", "t.value", "p.value")) %>% 
498
  data.frame() %>% 
499
  dplyr::mutate(IdentI=as.character(i)) %>% 
500
  rownames_to_column("Parameter")
501
502
}
503
504
p.value <- bind_rows(models, .id = "model") %>% 
505
  filter(Parameter!="(Intercept)") %>% 
506
  mutate(Entity=strsplit(model, split = "_") %>% sapply(., "[[", 2)) %>% 
507
  group_by(IdentI, Entity) %>% 
508
  mutate(p.adj=p.adjust(p.value, method = "BH")) %>% 
509
  mutate(sign=ifelse(Estimate<0 & p.adj<0.05, "-", NA)) %>% 
510
  mutate(sign=ifelse(Estimate>0 & p.adj<0.05, "+", sign)) %>% 
511
  mutate(Entity=factor(Entity, levels = c("Overall", "DLBCL", "MCL", "FL", "MZL")))
512
513
514
plot_multi <- ggplot()+
515
  geom_point(data=p.value %>% filter(Entity=="Overall"), aes(x=IdentI, y=Parameter, size=-log10(p.adj), fill=t.value), shape=21, stroke=0.25,
516
             position = position_nudge(y=0.16))+
517
  geom_point(data=p.value %>% filter(Entity!="Overall"), aes(x=IdentI, y=Parameter, size=-log10(p.adj), fill=t.value, group=Entity), shape=21, stroke=0.25, 
518
             position = ggpp::position_dodgenudge(y = -0.14, width = 0.78))+
519
  geom_text(data=p.value %>% filter(Entity=="Overall", p.adj<0.05), aes(x=IdentI, y=Parameter, label=round(p.adj, 3)), hjust=0.5, nudge_y = 0.4, size=2.5)+
520
  geom_text(data=p.value %>% filter(Entity=="Overall", p.adj<0.05), aes(x=IdentI, y=Parameter, label=sign), hjust=0.5, nudge_y = 0.18, size=2.5)+
521
  geom_text(data=p.value %>% filter(Entity!="Overall"), aes(x=IdentI, y=Parameter, label=sign, group=Entity), size=2.5, 
522
             position = ggpp::position_dodgenudge(y = -0.11, width = 0.78))+
523
  scale_x_discrete(limits=factor(cluster_order), labels=unlist(labels_cl))+
524
  scale_size_continuous(range=c(0.25,3.5), limits=c(0,3), name=expression('-log'[10]~'p'))+
525
  scale_fill_gradientn(colors=brewer.pal(9, name = "RdBu"), limits=c(-5, 5), breaks=c(-3,0,3), name="Statistic")+
526
  guides(fill=guide_colorbar(barwidth = 2.5))+
527
  guides(size=guide_legend(keywidth = 0.3))+
528
  geom_hline(yintercept = seq(1,6,1), color="grey90", size=0.25)+
529
  geom_vline(xintercept = seq(1.5,13.5,1), color="grey90", size=0.25)+
530
  scale_y_discrete(limits=rev(c("StatusRelapse",  "Age", "SexM", "Subtypenon-GCB")),
531
                   labels=rev(c("<b style='color:#B2182B'>Initial diagnosis </b><br>vs. <b style='color:#2166AC'>Relapse</b>",
532
                                "<b style='color:#B2182B'>Younger </b>vs.<br><b style='color:#2166AC'>Older</b>",
533
                                "<b style='color:#B2182B'>Female </b>vs.<br><b style='color:#2166AC'>Male</b>",
534
                                "<b style='color:#B2182B'>GCB</b> vs.<br><b style='color:#2166AC'>non-GCB</b><br>[only DLBCL]")))+
535
  mytheme_1+
536
  theme(axis.title = element_blank(),
537
        legend.position = "top",
538
        plot.title = element_text(margin = unit(c(0,0,0,0), units = "cm")),
539
        axis.text.x = element_text(angle = 45, hjust = 1),
540
        panel.border = element_rect(size=0.5),
541
        legend.key.height = unit(x = 0.3, units = "cm"),
542
        legend.box.margin = unit(c(0,-8.5,-0.35,0), "cm"),
543
        plot.margin = unit(c(0,0.25,0,0.25), "cm"),
544
        legend.key.width = unit(x = 0.35, units = "cm"),
545
        axis.text.y = element_markdown(hjust = 1,  lineheight = 1.2))+
546
  labs(tag = "B")
547
548
plot_coefs+labs(tag = "A")+plot_multi+plot_layout(heights = c(1.2,1))
549
550
ggsave(width = 18, height = 15, units = "cm", filename = "SF4.pdf")
551
552
```
553
554
# Supplementary Figure 5
555
## Proportions of T-cell subsets in 5' scRNA versus CITE-seq
556
### Data handling
557
```{r data handling SF5}
558
559
df_freq_5prime <- DFtotal_5prime %>% 
560
  select(Barcode_full, IdentI, PatientID) %>% 
561
  distinct() %>% 
562
  add_prop(vars = c("PatientID", "IdentI"), group.vars = 1) %>% 
563
  mutate(Class="5prime") %>% 
564
  filter(PatientID %in% unique(df_comb$PatientID))
565
566
df_freq_3prime <- df_comb %>% 
567
  add_prop(vars = c( "PatientID", "IdentI"), group.vars = 1) %>% 
568
  mutate(Class="3prime") %>% 
569
  filter(PatientID %in% DFtotal_5prime$PatientID)
570
571
df_freq_prime <- rbind(df_freq_3prime, df_freq_5prime) %>% 
572
  mutate(Prop=100*Prop) %>% 
573
  pivot_wider(names_from = "Class", values_from = "Prop", values_fill = 0) 
574
575
```
576
577
### Correlation plots
578
```{r cor plots SF5}
579
580
this_theme <- theme(plot.margin = unit(c(0,0.25,0.1,0), units = "cm"),
581
  plot.title = element_text(vjust = -1),
582
  axis.title = element_blank(),
583
  axis.text = element_text(size=7, color="black"))
584
585
cor_plots_prime <- list()
586
587
cor_plots_prime[["TFH"]] <- 
588
  df_freq_prime %>% 
589
  filter(IdentI==6) %>% 
590
  ggplot(aes(y=`5prime`, x=`3prime`))+
591
  geom_point(color=colors_umap_cl[["6"]], size=0.65, alpha=0.75)+
592
  geom_smooth(method = "lm", linetype="dashed", size=0.25, formula = y ~ x, na.rm = T,
593
              color=colors_umap_cl[["6"]], se=F, fullrange=T)+
594
  stat_cor(aes(label=..r.label..), method = "pearson", size=2.5, label.x.npc = c(0.45), label.y.npc = c(0.1))+
595
  scale_x_continuous(limits = c(0,60), breaks = c(0, 20, 40, 60))+
596
  scale_y_continuous(limits = c(0,60), breaks = c(0, 20, 40, 60))+
597
  labs(x="3' scRNA - %", y="5' scRNA - %")+
598
  ggtitle(labels_cl[["6"]])+
599
  theme_bw()+
600
  coord_fixed()+
601
  mytheme_1+
602
  this_theme
603
604
cor_plots_prime[["TPR"]] <- df_freq_prime %>% 
605
   filter(IdentI==14) %>% 
606
  ggplot(aes(y=`5prime`, x=`3prime`))+
607
  geom_point(color=colors_umap_cl[["14"]], size=0.65, alpha=0.75)+
608
  geom_smooth(method = "lm", linetype="dashed", size=0.25, formula = y ~ x, na.rm = T,
609
              color=colors_umap_cl[["14"]], se=F, fullrange=T)+
610
  stat_cor(aes(label=..r.label..), method = "pearson",size=2.5, label.x.npc = c(0.45), label.y.npc = c(0.1))+
611
  scale_x_continuous(limits = c(0,12), breaks = c(0, 4, 8, 12))+
612
  scale_y_continuous(limits = c(0,12), breaks = c(0, 4, 8, 12))+
613
  labs(x="3' scRNA - %", y="5' scRNA - %")+
614
  ggtitle(labels_cl[["14"]])+
615
  theme_bw()+
616
  coord_fixed()+
617
  mytheme_1+
618
  this_theme+
619
  theme(axis.title.y = element_text(size=7))
620
621
cor_plots_prime[["TDN"]] <- df_freq_prime %>% 
622
  filter(IdentI==19) %>% 
623
  ggplot(aes(y=`5prime`, x=`3prime`))+
624
  geom_point(color=colors_umap_cl[["19"]], size=0.65, alpha=0.75)+
625
  geom_smooth(method = "lm", linetype="dashed", size=0.25, formula = y ~ x, na.rm = T,
626
              color=colors_umap_cl[["19"]], se=F, fullrange=T)+
627
  stat_cor(aes(label=..r.label..), method = "pearson",size=2.5, label.x.npc = c(0.45), label.y.npc = c(0.1))+
628
  scale_x_continuous(limits = c(0,8), breaks = c(0, 2, 4, 6, 8))+
629
  scale_y_continuous(limits = c(0,8), breaks = c(0, 2, 4, 6, 8))+
630
  labs(x="3' scRNA - %", y="5' scRNA - %")+
631
  ggtitle(labels_cl[["19"]])+
632
  theme_bw()+
633
  coord_fixed()+
634
  mytheme_1+
635
  theme_axis_sub3
636
637
cor_plots_prime[["THCM2"]] <- df_freq_prime %>% 
638
  filter(IdentI==9) %>% 
639
  ggplot(aes(y=`5prime`, x=`3prime`))+
640
  geom_point(color=colors_umap_cl[["9"]], size=0.65, alpha=0.75)+
641
  geom_smooth(method = "lm", linetype="dashed", size=0.25, formula = y ~ x, na.rm = T,
642
              color=colors_umap_cl[["9"]], se=F, fullrange=T)+
643
  stat_cor(aes(label=..r.label..), method = "pearson",size=2.5, label.x.npc = c(0.45), label.y.npc = c(0.1))+
644
  scale_x_continuous(limits = c(0,15), breaks = c(0, 5, 10, 15))+
645
  scale_y_continuous(limits = c(0,15), breaks = c(0, 5, 10, 15))+
646
  labs(x="3' scRNA - %", y="5' scRNA - %")+
647
  ggtitle(labels_cl[["9"]])+
648
  theme_bw()+
649
  coord_fixed()+
650
  mytheme_1+
651
  this_theme
652
653
cor_plots_prime[["THCM1"]] <- df_freq_prime %>% 
654
  filter(IdentI==2) %>% 
655
  ggplot(aes(y=`5prime`, x=`3prime`))+
656
  geom_point(color=colors_umap_cl[["2"]], size=0.65, alpha=0.75)+
657
  geom_smooth(method = "lm", linetype="dashed", size=0.25, formula = y ~ x, na.rm = T,
658
              color=colors_umap_cl[["2"]], se=F, fullrange=T)+
659
  stat_cor(aes(label=..r.label..), method = "pearson",size=2.5, label.x.npc = c(0.45), label.y.npc = c(0.1))+
660
  scale_x_continuous(limits = c(0,20), breaks = c(0, 6, 12, 18))+
661
  scale_y_continuous(limits = c(0,20), breaks = c(0, 6, 12, 18))+
662
  labs(x="3' scRNA - %", y="5' scRNA - %")+
663
  ggtitle(labels_cl[["2"]])+
664
  theme_bw()+
665
  coord_fixed()+
666
  mytheme_1+
667
  this_theme
668
669
670
cor_plots_prime[["THNaive"]] <- df_freq_prime %>% 
671
  filter(IdentI==1) %>% 
672
  ggplot(aes(y=`5prime`, x=`3prime`))+
673
  geom_point(color=colors_umap_cl[["1"]], size=0.65, alpha=0.75)+
674
  geom_smooth(method = "lm", linetype="dashed", size=0.25, formula = y ~ x, na.rm = T,
675
              color=colors_umap_cl[["1"]], se=F, fullrange=T)+
676
  stat_cor(aes(label=..r.label..), method = "pearson",size=2.5, label.x.npc = c(0.45), label.y.npc = c(0.1))+
677
  scale_x_continuous(limits = c(0,45), breaks = c(0, 15, 30, 45))+
678
  scale_y_continuous(limits = c(0,45), breaks = c(0, 15, 30, 45))+
679
  labs(x="3' scRNA - %", y="5' scRNA - %")+
680
  ggtitle(labels_cl[["1"]])+
681
  theme_bw()+
682
  coord_fixed()+
683
  mytheme_1+
684
  this_theme
685
686
cor_plots_prime[["TREGCM1"]] <- df_freq_prime %>% 
687
  filter(IdentI==8) %>% 
688
  ggplot(aes(y=`5prime`, x=`3prime`))+
689
  geom_point(color=colors_umap_cl[["8"]], size=0.65, alpha=0.75)+
690
  geom_smooth(method = "lm", linetype="dashed", size=0.25, formula = y ~ x, na.rm = T,
691
              color=colors_umap_cl[["8"]], se=F, fullrange=T)+
692
  stat_cor(aes(label=..r.label..), method = "pearson",size=2.5, label.x.npc = c(0.45), label.y.npc = c(0.1))+
693
  labs(x="3' scRNA - %", y="5' scRNA - %")+
694
  ggtitle(labels_cl[["8"]])+
695
    scale_x_continuous(limits = c(0,25), breaks = c(0, 8, 16, 24))+
696
  scale_y_continuous(limits = c(0,25), breaks = c(0, 8, 16, 24))+
697
  theme_bw()+
698
  coord_fixed()+
699
  mytheme_1+
700
  this_theme
701
702
cor_plots_prime[["TREGEM2"]] <- df_freq_prime %>% 
703
  filter(IdentI==11) %>% 
704
  ggplot(aes(y=`5prime`, x=`3prime`))+
705
  geom_point(color=colors_umap_cl[["11"]],size=0.65, alpha=0.75)+
706
  geom_smooth(method = "lm", linetype="dashed", size=0.25, formula = y ~ x, na.rm = T,
707
              color=colors_umap_cl[["11"]], se=F, fullrange=T)+
708
  stat_cor(aes(label=..r.label..), method = "pearson",size=2.5, label.x.npc = c(0.45), label.y.npc = c(0.1))+
709
  scale_x_continuous(limits = c(0,16), breaks = c(0, 5, 10, 15))+
710
  scale_y_continuous(limits = c(0,16), breaks = c(0, 5, 10, 15))+
711
  labs(x="3' scRNA - %", y="5' scRNA - %")+
712
  ggtitle(labels_cl[["11"]])+
713
  theme_bw()+
714
  coord_fixed()+
715
  mytheme_1+
716
  theme_axis_sub3
717
718
cor_plots_prime[["TREGEM1"]] <- df_freq_prime %>% 
719
  filter(IdentI==15) %>% 
720
  ggplot(aes(y=`5prime`, x=`3prime`))+
721
  geom_point(color=colors_umap_cl[["15"]], size=0.65, alpha=0.75)+
722
  geom_smooth(method = "lm", linetype="dashed", size=0.25, formula = y ~ x, na.rm = T,
723
              color=colors_umap_cl[["15"]], se=F, fullrange=T)+
724
  stat_cor(aes(label=..r.label..), method = "pearson",size=2.5, label.x.npc = c(0.45), label.y.npc = c(0.1))+
725
  scale_x_continuous(limits = c(0,20), breaks = c(0, 6, 12, 18))+
726
  scale_y_continuous(limits = c(0,20), breaks = c(0, 6, 12, 18))+
727
  labs(x="3' scRNA - %", y="5' scRNA - %")+
728
  ggtitle(labels_cl[["15"]])+
729
  theme_bw()+
730
  coord_fixed()+
731
  mytheme_1+
732
  this_theme+
733
  theme(axis.title.y = element_text(size=7),
734
        axis.title.x = element_text(size=7))
735
736
cor_plots_prime[["TREGCM2"]] <- df_freq_prime %>% 
737
  filter(IdentI==13) %>% 
738
  ggplot(aes(y=`5prime`, x=`3prime`))+
739
  geom_point(color=colors_umap_cl[["13"]], size=0.65, alpha=0.75)+
740
  geom_smooth(method = "lm", linetype="dashed", size=0.25, formula = y ~ x, na.rm = T,
741
              color=colors_umap_cl[["13"]], se=F, fullrange=T)+
742
  stat_cor(aes(label=..r.label..), method = "pearson",size=2.5, label.x.npc = c(0.45), label.y.npc = c(0.1))+
743
  scale_x_continuous(limits = c(0,20), breaks = c(0, 6, 12, 18))+
744
  scale_y_continuous(limits = c(0,20), breaks = c(0, 6, 12, 18))+
745
  labs(x="3' scRNA - %", y="5' scRNA - %")+
746
  ggtitle(labels_cl[["13"]])+
747
  theme_bw()+
748
  coord_fixed()+
749
  mytheme_1+
750
  this_theme
751
752
cor_plots_prime[["TTOXNaive"]] <-df_freq_prime %>% 
753
  filter(IdentI==12) %>% 
754
  ggplot(aes(y=`5prime`, x=`3prime`))+
755
  geom_point(color=colors_umap_cl[["12"]], size=0.65, alpha=0.75)+
756
  geom_smooth(method = "lm", linetype="dashed", size=0.25, formula = y ~ x, na.rm = T,
757
              color=colors_umap_cl[["12"]], se=F, fullrange=T)+
758
  stat_cor(aes(label=..r.label..), method = "pearson",size=2.5, label.x.npc = c(0.45), label.y.npc = c(0.1))+
759
  scale_x_continuous(limits = c(0,27), breaks = c(0, 8, 16, 24))+
760
  scale_y_continuous(limits = c(0,27), breaks = c(0, 8, 16, 24))+
761
  labs(x="3' scRNA - %", y="5' scRNA - %")+
762
  ggtitle(labels_cl[["12"]])+
763
  theme_bw()+
764
  coord_fixed()+
765
  mytheme_1+
766
  theme_axis_sub3
767
 
768
cor_plots_prime[["TTOXEM3"]] <- df_freq_prime %>% 
769
  filter(IdentI==5) %>% 
770
  ggplot(aes(y=`5prime`, x=`3prime`))+
771
  geom_point(color="#b50923", size=0.65, alpha=0.75)+
772
  geom_smooth(method = "lm", linetype="dashed", size=0.25, formula = y ~ x, na.rm = T,
773
              color="#b50923", se=F, fullrange=T)+
774
  stat_cor(aes(label=..r.label..), method = "pearson",size=2.5, label.x.npc = c(0.45), label.y.npc = c(0.1))+
775
  scale_x_continuous(limits = c(0,80), breaks = c(0, 25, 50, 75))+
776
  scale_y_continuous(limits = c(0,80), breaks = c(0, 25, 50, 75))+
777
  labs(x="3' scRNA - %", y="5' scRNA - %")+
778
  ggtitle(labels_cl[["5"]])+
779
  theme_bw()+
780
  coord_fixed()+
781
  mytheme_1+
782
  theme_axis_sub3
783
784
cor_plots_prime[["TTOXEM1"]] <- df_freq_prime %>% 
785
  filter(IdentI==3) %>% 
786
  ggplot(aes(y=`5prime`, x=`3prime`))+
787
  geom_point(color="#fea044", size=0.65, alpha=0.75)+
788
  geom_smooth(method = "lm", linetype="dashed", size=0.25, formula = y ~ x,na.rm = T,
789
              color="#fea044", se=F, fullrange=T)+
790
  stat_cor(aes(label=..r.label..), method = "pearson",size=2.5, label.x.npc = c(0.45), label.y.npc = c(0.1))+
791
  scale_x_continuous(limits = c(0,50), breaks = c(0, 15, 30, 45))+
792
  scale_y_continuous(limits = c(0,50), breaks = c(0, 15, 30, 45))+
793
  labs(x="3' scRNA - %", y="5' scRNA - %")+
794
  ggtitle(labels_cl[["3"]])+
795
  theme_bw()+
796
  coord_fixed()+
797
  mytheme_1+
798
  theme_axis_sub3
799
800
cor_plots_prime[["TTOXEM2"]] <- df_freq_prime %>% 
801
  filter(IdentI==16) %>% 
802
  ggplot(aes(y=`5prime`, x=`3prime`))+
803
  geom_point(color=colors_umap_cl[["16"]], size=0.65, alpha=0.75)+
804
  geom_smooth(method = "lm", linetype="dashed", size=0.25, formula = y ~ x, na.rm = T,
805
              color=colors_umap_cl[["16"]], se=F, fullrange=T)+
806
  stat_cor(aes(label=..r.label..), method = "pearson",size=2.5, label.x.npc = c(0.45), label.y.npc = c(0.9))+
807
  scale_x_continuous(limits = c(0,15), breaks = c(0, 4, 8, 12))+
808
  scale_y_continuous(limits = c(0,15), breaks = c(0, 4, 8, 12))+
809
  labs(x="3' scRNA - %", y="5' scRNA - %")+
810
  ggtitle(labels_cl[["16"]])+
811
  theme_bw()+
812
  coord_fixed()+
813
  mytheme_1+
814
  theme_axis_sub3
815
816
cor_plots_prime_all <- cor_plots_prime$TPR+labs(tag ="A")+
817
  cor_plots_prime$THNaive+cor_plots_prime$THCM1+cor_plots_prime$THCM2+cor_plots_prime$TFH+
818
  cor_plots_prime$TREGCM1+cor_plots_prime$TREGCM2+cor_plots_prime$TREGEM1+cor_plots_prime$TREGEM2+
819
  cor_plots_prime$TTOXNaive+cor_plots_prime$TTOXEM1+cor_plots_prime$TTOXEM2+cor_plots_prime$TTOXEM3+
820
  cor_plots_prime$TDN+
821
  plot_layout(nrow = 2)
822
823
df_freq_prime %>% 
824
  group_by(IdentI) %>% 
825
  summarise(R=cor.test(`3prime`, `5prime`)$estimate) %>% pull(R) %>% median()
826
827
```
828
829
## CD4 and CD8 expression in clonal T-cells
830
```{r CD4 and CD8 expression in SF5}
831
832
lim_CD4 <- 0.3
833
lim_CD8 <- 0.6
834
835
df_clone_expr <- lapply(sobjs_T_5prime, function(sobj){
836
  FetchData(sobj, vars=c("CD4", "CD8A")) %>% 
837
              data.frame() %>% 
838
              rownames_to_column("Barcode_full")
839
  }) %>% bind_rows() %>% remove_rownames()
840
841
df_clone_CD4 <- DFtotal_5prime %>% 
842
  select(Barcode_full, PatientID, refUMAP_1, refUMAP_2, Entity, IdentI, raw_clonotype_id) %>% 
843
  distinct() %>% 
844
  add_count(IdentI, PatientID, raw_clonotype_id) %>% 
845
  left_join(., df_clone_expr) %>% 
846
  mutate(IdentI_new=factor(IdentI, levels = cluster_order, labels = labels_cl_parsed)) %>% 
847
  filter(IdentI %in% c(3,5)) %>% 
848
  mutate(Expanded=n>2) %>% 
849
  mutate(CD4CD8=case_when(CD4 > lim_CD4 & CD8A < lim_CD8 ~ "CD4pos",
850
                          CD4 < lim_CD4 & CD8A > lim_CD8 ~ "CD8pos",
851
                          CD4 > lim_CD4 & CD8A > lim_CD8 ~ "CD4CD8pos",
852
                          CD4 < lim_CD4 & CD8A < lim_CD8 ~ "CD4CD8neg"))
853
  
854
df_clone_CD4_freq <- df_clone_CD4 %>% 
855
  drop_na() %>% 
856
  add_prop(vars = c("IdentI", "Expanded", "CD4CD8"), group.vars = c(1,2)) %>% 
857
  fill_zeros(names_from = "IdentI", values_from = "Prop") %>% 
858
  mutate(Prop=round(Prop, 2)) %>% 
859
  left_join(., data.frame(CD4CD8=c("CD4CD8neg", "CD4pos", "CD4CD8pos",  "CD8pos"), 
860
                          CD8=c(-0.35, -0.35, 3.7, 3.7),
861
                          CD4=c(-0.35, 1.9, 1.9, -0.35))) %>% 
862
    mutate(IdentI_new=factor(IdentI, levels = cluster_order, labels = labels_cl_parsed)) 
863
  
864
plot_expr1 <- ggplot()+
865
  geom_point(data=df_clone_CD4 %>% filter(n<3), inherit.aes = F, aes(x=CD4, y=CD8A, color=IdentI), 
866
             position = position_jitter(width = 0.1, height = 0.1),  na.rm = T,
867
             size=0.25, alpha=0.25, stroke=0)+
868
  scale_color_manual(values = colors_umap_cl, guide="none")+
869
  scale_fill_manual(values = colors_umap_cl, guide="none")+
870
  geom_text(data=df_clone_CD4_freq %>% filter(Expanded==F), inherit.aes = F, aes(x=CD4, y=CD8, label=Prop), size=2.5, alpha=1)+
871
  geom_hline(yintercept = 0.6, linetype="dashed", size=0.25)+
872
  geom_vline(xintercept = 0.3, linetype="dashed", size=0.25)+
873
  scale_x_continuous(breaks = c(0,0.5,1,1.5,2), limits=c(-0.5, 2.4))+
874
  scale_y_continuous(breaks = c(0,1,2,3), limits=c(-0.5, 4))+
875
  labs(x="<i>CD4</i> - RNA expression",
876
       y="<i>CD8</i> - RNA expression",
877
       title="Clone size < 3",
878
       tag = "B")+
879
  facet_wrap(~IdentI_new, nrow = 1, labeller = label_parsed)+
880
  mytheme_1+
881
  theme(axis.title.x = element_textbox(size=7, halign = 0.5, margin = unit(units = "cm", c(0.1,0,0,0))),
882
        axis.title.y = element_textbox(size=7, orientation = "left-rotated", margin = unit(units = "cm", c(0,0,0.1,0))),
883
        panel.border = element_rect(size=0.4))
884
885
plot_expr2 <- ggplot()+
886
  geom_point(data=df_clone_CD4 %>% filter(n>2), inherit.aes = F, aes(x=CD4, y=CD8A, color=IdentI),
887
             position =  position_jitter(width = 0.1, height = 0.1), na.rm = T,
888
             size=0.25, alpha=0.25, stroke=0)+
889
  scale_color_manual(values = colors_umap_cl, guide="none")+
890
  scale_fill_manual(values = colors_umap_cl, guide="none")+
891
  scale_size_continuous(range=c(1, 5), limits=c(3, 50), breaks=c(3, 20, 35, 50),
892
                        labels=c("3", "20", "35", "> 50"), name = "Clonotype size")+
893
  geom_hline(yintercept = 0.6, linetype="dashed", size=0.25)+
894
  geom_vline(xintercept = 0.3, linetype="dashed", size=0.25)+
895
  geom_text(data=df_clone_CD4_freq %>% filter(Expanded==T), inherit.aes = F, aes(x=CD4, y=CD8, label=Prop), size=2.5, alpha=1)+
896
  facet_wrap(~IdentI_new, nrow = 1, labeller = label_parsed)+
897
  scale_x_continuous(breaks = c(0,0.5,1,1.5,2), limits=c(-0.5, 2.4))+
898
  scale_y_continuous(breaks = c(0,1,2,3), limits=c(-0.5, 4))+
899
  labs(x="<i>CD4</i> - RNA expression",
900
       y="<i>CD8</i> - RNA expression",
901
       title="Clone size > 2",
902
       tag = "C")+
903
  facet_wrap(~IdentI_new, nrow = 1, labeller = label_parsed)+
904
  mytheme_1+
905
  theme(axis.title.x = element_textbox(size=7, halign = 0.5, margin = unit(units = "cm", c(0.1,0,0,0))),
906
        axis.title.y = element_textbox(size=7, orientation = "left-rotated", margin = unit(units = "cm", c(0,0,0.1,0))),
907
        panel.border = element_rect(size=0.4))
908
909
```
910
911
## Assemble plot
912
```{r assemble SF5}
913
914
cor_plots_prime_all/wrap_plots(plot_expr1+plot_spacer()+plot_expr2+plot_layout(widths = c(1,0.1,1)))+
915
  plot_layout(heights = c(1.6,1))
916
917
#ggsave(width = 18.5, height = 12.5, units = "cm", filename = "SF5.pdf")
918
919
```
920
921
## TCR diversity
922
### Read
923
```{r TCR diversity read}
924
925
# Single cell T-cell receptor data read by immunarch package
926
# RNA–seq, epitope and TCR raw and processed data have been deposited in the Gene Expression Omnibus (GEO) under accession codes GSE252608 and GSE252455.
927
DF_immunarchTCR <- repLoad(list.files(path = "countMatrices", pattern = "TCRrep", full.names = T))
928
DF_immunarchTCR$meta$Sample <- strsplit(DF_immunarchTCR$meta$Sample, split = "_") %>% sapply("[[", 1)
929
names(DF_immunarchTCR$data) <- DF_immunarchTCR$meta$Sample
930
931
```
932
933
### Plot
934
```{r TCR diversity plot, fig.height=3.5}
935
936
plots <- list()
937
for(i in unique(DFtotal_5prime$PatientID)){
938
set.seed(substr(i, 4,7) %>% as.numeric()+5)
939
plots[[i]] <- 
940
  DFtotal_5prime %>% filter(PatientID==i) %>% 
941
  select(Barcode_full, PatientID, raw_clonotype_id) %>% 
942
  distinct() %>% 
943
  dplyr::count(raw_clonotype_id) %>% 
944
  drop_na() %>% 
945
  mutate(Prop=n/sum(n)) %>% 
946
  dplyr::arrange(-n) %>% 
947
  mutate(Cumsum=cumsum(n)) %>% 
948
  mutate(Max=sum(n)) %>% 
949
  filter(Cumsum < 0.1*Max) %>% 
950
  mutate(new_id=as.character(1:nrow(.))) %>% 
951
  mutate(PatientID=i) %>% 
952
  add_entity() %>% 
953
  mutate(PatientID_new=paste0(PatientID, " (", Entity, ")")) %>% 
954
  ggplot(aes(x=new_id, y=n))+
955
  geom_segment(aes(x=new_id, xend=new_id, y=0, yend=n), size=0.2)+
956
  facet_wrap(~PatientID_new)+
957
  xlab("Clonotype ID")+
958
  scale_y_continuous(name =  "Clonotype size")+
959
  scale_x_discrete(limits=sample(as.character(1:195), 195), name="Unique clonotype ID")+
960
  mytheme_1+
961
  theme(legend.position = "none",
962
        panel.border = element_rect(size=0.4),
963
        strip.background = element_rect(colour = NA),
964
        axis.title.x = element_text(vjust = 5),
965
        axis.text.x = element_blank(),
966
        axis.ticks.x = element_blank())
967
968
}
969
970
imm_raref <- repDiversity(DF_immunarchTCR$data, "raref", .verbose = F) %>% 
971
  rename(PatientID=Sample) %>% 
972
  add_entity() %>% 
973
  filter(!PatientID %in% c("LN0256", "LN0367"))
974
975
tops <- imm_raref %>% 
976
  group_by(PatientID) %>% 
977
  top_n(n=1, Size) %>% 
978
  #mutate(Mean=ifelse(PatientID=="LN0302", 5.0, Mean)) %>% 
979
  mutate(Size=ifelse(PatientID=="LN0132", 88, Size)) %>% 
980
  mutate(Size=ifelse(PatientID=="LN0110", 72, Size)) %>% 
981
  mutate(Mean=ifelse(PatientID=="LN0110", 19, Mean)) %>% 
982
  mutate(Size=ifelse(PatientID=="LN0259", 90, Size)) %>% 
983
  mutate(Mean=ifelse(PatientID=="LN0259", 20.75, Mean)) %>% 
984
  mutate(Size=ifelse(PatientID=="LN0264", 55, Size)) %>% 
985
  mutate(Mean=ifelse(PatientID=="LN0264", 13.5, Mean)) %>% 
986
  mutate(Size=ifelse(PatientID=="LN0217", Size-10, Size)) %>% 
987
  mutate(Size=ifelse(PatientID=="LN0144", 145, Size)) %>% 
988
  mutate(Mean=ifelse(PatientID=="LN0193", Mean+1, Mean)) %>% 
989
  mutate(Size=ifelse(PatientID=="LN0198", 115, Size)) %>% 
990
  mutate(Mean=ifelse(PatientID=="LN0198", Mean+0.2, Mean)) %>% 
991
  mutate(Mean=ifelse(PatientID=="LN0278", Mean+1, Mean)) %>% 
992
  mutate(Mean=ifelse(PatientID=="LN0144", Mean+0.75, Mean)) %>% 
993
  mutate(Mean=ifelse(PatientID=="LN0302", Mean-1.5, Mean)) %>% 
994
  mutate(Size=ifelse(PatientID=="LN0302", 50, Size)) %>% 
995
  filter(!PatientID %in% c("LN0417", "LN0104", "LN0249")) # Manuel labelling in Powerpoint
996
997
plot_rare <- 
998
  imm_raref %>%
999
  ggplot(aes(x=Size, y=Mean, group=PatientID, color=Entity))+
1000
  geom_line(linetype="solid", size=0.25)+
1001
  geom_label(data=tops, aes(x=Size, y=Mean, label=PatientID),  size=2.25, 
1002
                            show.legend = F, fill="white", color="white", 
1003
                            label.padding = unit(units = "cm", 0.02), label.size = 0)+
1004
  geom_text(data=tops, aes(x=Size, y=Mean, label=PatientID), size=2, show.legend = F)+
1005
  guides(color=guide_legend(override.aes = list(size=0.35, linetype="solid")))+
1006
  scale_color_brewer(palette = "Paired", limits=c("DLBCL", "MCL", "FL", "MZL", "rLN"))+
1007
  ylab("Estimated diversity")+
1008
  xlab("Clone size")+
1009
  #xlim(0, 70)+
1010
  mytheme_1+
1011
  theme(#legend.position = "top",
1012
        legend.title = element_blank(),
1013
        panel.grid = element_blank(),
1014
        legend.spacing.x = unit("cm", x = 0.05),
1015
        legend.box.margin = unit(c(0,0,-0.95,0), "cm"),
1016
        panel.border = element_rect(size=0.4),
1017
        legend.key.height = unit("cm", x = 0.36),
1018
        legend.key.width = unit("cm", x = 0.5))+
1019
  labs(tag = "D")
1020
1021
plot_rare+wrap_plots((plots$LN0132+theme(axis.title.x = element_blank())+labs(tag = "E"))/plots$LN0217+labs(tag = "F"))+
1022
  plot_layout(widths = c(1,1.7))
1023
  
1024
#ggsave(width = 18, height = 8, units = "cm", filename = "SF5.pdf")
1025
1026
```
1027
1028
# Supplementary Figure 6
1029
## T-cell exhaustion UMAP
1030
### Calculate exhaustion module
1031
```{r calculate exhaustion module}
1032
1033
exhausted_cells <- ttox@meta.data %>%
1034
  mutate(Exhausted=ifelse( Pseudotime>=24, "yes", "no")) %>% 
1035
  filter(Exhausted=="yes") %>% rownames()
1036
1037
Combined_T@meta.data$Exhausted <- Combined_T@meta.data %>% 
1038
  mutate(Exhausted=Barcode_full %in% exhausted_cells) %>% 
1039
  pull(Exhausted)
1040
1041
Idents(Combined_T) <- "Exhausted"
1042
1043
module_exhausted <- FindMarkers(Combined_T, ident.1 = "TRUE", assay = "integratedRNA", test.use = "roc") %>% 
1044
  rownames_to_column("Gene") %>% 
1045
  mutate(Module=paste0(Gene, ifelse(myAUC>0.5, "+", "-")),
1046
         Assay="RNA")
1047
1048
module_exhausted_prot <- FindMarkers(Combined_T, ident.1 = "TRUE", assay = "integratedADT", test.use = "roc") %>% 
1049
  rownames_to_column("Gene") %>% 
1050
  mutate(Module=paste0(Gene, ifelse(myAUC>0.5, "+", "-")),
1051
         Assay="Protein")
1052
1053
#module_exhausted --> Supplementary Table 5
1054
#WriteXLS::WriteXLS(rbind(module_exhausted, module_exhausted_prot), ExcelFileName = "SuppTable5.xlsx")
1055
1056
module_exhausted <- list(module_exhausted$Module)
1057
names(module_exhausted) <- "exhausted"
1058
1059
Combined_T <- UCell::AddModuleScore_UCell(Combined_T, features = module_exhausted)
1060
1061
```
1062
1063
### Plot exhaustion module
1064
```{r plot exhaustion module}
1065
1066
set.seed(1)
1067
plot_exh <- FetchData(Combined_T, vars = c("wnnUMAP_1", "wnnUMAP_2", "exhausted_UCell")) %>% 
1068
  sample_frac(0.2) %>% 
1069
  ggplot(aes(x=wnnUMAP_1, y=wnnUMAP_2, fill= exhausted_UCell))+
1070
  ggrastr::geom_point_rast(size=0.25, stroke=0, shape=21, raster.dpi = 600, alpha=0.75)+
1071
  scale_fill_gradientn(colours = brewer.pal(n = 9, name = "YlOrRd")[2:9],
1072
                       name="Score")+
1073
  xlab("wnnUMAP-1")+
1074
  ylab("wnnUMAP-2")+
1075
  ggtitle("Exhaustion signature")+
1076
  mytheme_1+
1077
  theme(panel.border = element_rect(size = 0.2),
1078
        axis.title.x = element_text(margin = unit(units = "cm", c(-0.75,0,0,0))),
1079
        #legend.margin = margin(c(0,0,0,-0.35), unit = "cm"),
1080
        legend.box.margin = unit(c(0,0,0,-0.35), units = "cm"),
1081
        legend.title = element_text(size=6),
1082
        legend.text = element_text(size=6),
1083
        legend.position = "right",
1084
        plot.title = element_text(face = "plain", vjust = -0.5),
1085
        panel.background = element_rect(fill=NA),
1086
        legend.key.height = unit(units="cm", 0.2),
1087
        legend.key.width = unit(units="cm", 0.15),
1088
        legend.box.background = element_rect(fill=NA, color=NA),
1089
        legend.background = element_rect(fill=NA, color=NA)
1090
        )+
1091
  labs(tag="A")
1092
1093
```
1094
1095
## Association with cell-of-origin in DLBCL
1096
```{r SF6 part 1}
1097
1098
### Schmitz
1099
p1 <- left_join(df_surv_schmitz, df_ttoxcompl_schmitz) %>% 
1100
  drop_na() %>% 
1101
  ggplot(aes(x=Subtype, y=Exhausted/Absolute, group=Subtype))+
1102
  geom_boxplot(outlier.alpha = 0, width=0.4, size=0.25)+
1103
  stat_compare_means(size=2.25, vjust = 1, aes(label=paste0("p = ", ..p.format..)))+
1104
  stat_compare_means(comparisons = list(c("ABC", "GCB")), size=2.25)+
1105
  scale_y_continuous(limits=c(0, 0.65), name = "Exhausted T-cells")+
1106
  #ggtitle("Schmitz et al. 2018")+
1107
  xlab("Cell-of-origin")+
1108
  mytheme_1+
1109
  theme(axis.text.x = element_text(angle = 45, hjust = 1),
1110
        #axis.title.x = element_text(margin = unit(units = "cm", c(-0.1,0,0,0))),
1111
        plot.title = element_text(face = "plain", vjust = -0.5))+
1112
  labs(tag = "B")
1113
1114
### Chapuy
1115
p2 <- left_join(df_surv_chapuy, df_ttoxcompl_chapuy) %>% 
1116
  drop_na() %>% 
1117
  ggplot(aes(x=Subtype, y=Exhausted/Absolute, group=Subtype))+
1118
  geom_boxplot(outlier.alpha = 0, width=0.4, size=0.25)+
1119
  stat_compare_means(size=2.25, vjust = 1, aes(label=paste0("p = ", ..p.format..)))+
1120
  scale_y_continuous(limits=c(0, 0.65), name="Exhausted T-cells")+
1121
  #ggtitle("Chapuy et al. 2018")+
1122
  xlab("Cell-of-origin")+
1123
  mytheme_1+
1124
  theme(axis.text.x = element_text(angle = 45, hjust = 1),
1125
        #axis.title.x = element_text(margin = unit(units = "cm", c(-0.1,0,0,0))),
1126
        plot.title = element_text(face = "plain", vjust = -0.5))+
1127
  labs(tag = "C")
1128
1129
```
1130
1131
## Association with genetic Subtype
1132
```{r SF6 part 2}
1133
1134
### Schmitz
1135
p3 <- left_join(df_surv_schmitz, df_ttoxcompl_schmitz) %>% 
1136
  drop_na() %>% 
1137
  ggplot(aes(x=GenSubtype, y=Exhausted/Absolute, group=GenSubtype))+
1138
  geom_boxplot(outlier.alpha = 0, width=0.4, size=0.25)+
1139
  stat_compare_means(size=2.25, vjust = 1, aes(label=paste0("p = ", ..p.format..)))+
1140
  scale_y_continuous(limits = c(0, 0.65), name="Exhausted T-cells")+
1141
  #ggtitle("Schmitz et al. 2018")+
1142
  xlab("Cluster")+
1143
  mytheme_1+
1144
  theme(axis.text.x = element_text(angle = 45, hjust = 1),
1145
        plot.title = element_text(face = "plain", vjust = -0.5),
1146
        axis.title.y = element_blank(),
1147
        axis.text.y = element_blank(),
1148
        axis.ticks.y = element_blank(),
1149
        #axis.title.x = element_text(margin = unit(units = "cm", c(-0.1,0,0,0)))
1150
        )
1151
1152
### Chapuy
1153
p4 <- left_join(df_surv_chapuy, df_ttoxcompl_chapuy) %>% 
1154
  drop_na() %>% 
1155
  mutate(Cluster=paste0("C", Cluster)) %>% 
1156
  ggplot(aes(x=Cluster, y=Exhausted/Absolute, group=Cluster))+
1157
  geom_boxplot(outlier.alpha = 0, width=0.4, size=0.25)+
1158
  stat_compare_means(size=2.25, vjust = 1, aes(label=paste0("p = ", ..p.format..)))+
1159
  scale_y_continuous(limits=c(0, 0.65), name="Exhausted T-cells")+
1160
  #ggtitle("Chapuy et al. 2018")+
1161
  xlab("Cluster")+
1162
  mytheme_1+
1163
  theme(axis.text.x = element_text(angle = 45, hjust = 1),
1164
        plot.title = element_text(face = "plain", vjust = -0.5),
1165
        axis.title.y = element_blank(),
1166
        axis.text.y = element_blank(),
1167
        axis.ticks.y = element_blank(),
1168
        #axis.title.x = element_text(margin = unit(units = "cm", c(-0.65,0,0,0)))
1169
        )
1170
1171
```
1172
1173
## Assemble plot
1174
### Part 1
1175
```{r assemble plot SF6 part 1, fig.height=2.5}
1176
1177
plot_exh+p1+p3+p2+p4+plot_layout(nrow = 1, widths = c(1.4,0.75,1,0.75,1))
1178
1179
#ggsave(width = 19, height = 6, units = "cm", filename = "SF6_p1.pdf")
1180
1181
```
1182
1183
1184
## Associations with genetic features
1185
### Mutations
1186
```{r mutations SF6}
1187
1188
pairs <- list(c(1:42), c(43:85))
1189
1190
df_mut <- df_snvs_chapuy %>% 
1191
  filter(Description=="Mutation", value %in% c(0,2)) %>% 
1192
  mutate(value=factor(value, levels = c("0", "2"), labels = c("wt", "mut"))) %>% 
1193
  group_by(Name, value) %>%
1194
  dplyr::summarise(MeanExhausted=mean(Exhausted/Absolute)) %>% 
1195
  mutate(MeanExhausted=ifelse(MeanExhausted>0.15, 0.15, MeanExhausted),
1196
         Group=case_when(Name %in% unique(.$Name)[pairs[[1]]] ~ "group1",
1197
                         Name %in% unique(.$Name)[pairs[[2]]] ~ "group2")) 
1198
1199
p.values <- df_snvs_chapuy %>% 
1200
  filter(Description=="Mutation", value %in% c(0,2)) %>% 
1201
  mutate(Exhausted=Exhausted/Absolute) %>% 
1202
  compare_means(formula = Exhausted ~ value, group.by = "Name", p.adjust.method = "BH") %>% 
1203
  filter(p<0.05) %>% 
1204
  left_join(., df_mut %>% select(Name, Group), by="Name")
1205
1206
p5 <- df_mut %>% 
1207
  ggplot(aes(x=value, y=Name, fill=MeanExhausted))+
1208
  geom_tile()+
1209
  scale_fill_gradientn(name="Expression", colours = brewer.pal(5, "PRGn"), limits=c(0,0.17))+
1210
  geom_vline(xintercept = 1.5, color="black", size=0.25)+
1211
  geom_segment(data=data.frame(y=seq(1.5, 42.5,1)), inherit.aes = F, 
1212
               aes(y = y, yend = y, x=0.05, xend=2.8), color="white", size=0.25)+
1213
  geom_text(data = p.values, inherit.aes = F, aes(y=Name, x=2.8, label=round(p, 2)), size=2.5)+
1214
  facet_wrap(~Group, ncol=3, scales = "free_y")+
1215
  ggtitle("Mutations")+
1216
  coord_cartesian(clip = "off")+
1217
  mytheme_1+
1218
  theme(strip.background = element_blank(),
1219
        strip.text = element_blank(),
1220
        axis.text.x = element_text(angle=45, hjust=1, size=7),
1221
        axis.ticks = element_blank(),
1222
        axis.text.y = element_text(size=7, margin = unit(c(0,-0.4,0,0), units = "cm")),
1223
        plot.margin = unit(units = "cm", c(0,1.25,0,0)),
1224
        axis.title = element_blank(),
1225
        panel.border = element_blank())+
1226
  labs(tag = "E")
1227
1228
```
1229
1230
### Copy number gain
1231
```{r copy number SF6}
1232
1233
df_gain <- df_snvs_chapuy %>% 
1234
  filter(Description=="CN gain") %>% 
1235
  mutate(value=factor(value, levels = c("0", "1", "2"), labels = c("wt", "gain", "gain"))) %>% 
1236
  group_by(Name, value) %>%
1237
  dplyr::summarise(MeanExhausted=mean(Exhausted/Absolute)) 
1238
1239
p.values <- df_snvs_chapuy %>% 
1240
  filter(Description=="CN gain") %>% 
1241
  mutate(Exhausted=Exhausted/Absolute) %>% 
1242
  mutate(value=factor(value, levels = c("0", "1", "2"), labels = c("wt", "gain", "gain"))) %>% 
1243
  compare_means(formula = Exhausted ~ value, group.by = "Name", p.adjust.method = "BH") %>% 
1244
  filter(p<0.05)
1245
1246
p6 <- df_gain %>% 
1247
  ggplot(aes(x=value, y=Name, fill=MeanExhausted))+
1248
  geom_tile()+
1249
  scale_fill_gradientn(name="Expression", colours = brewer.pal(5, "PRGn"), limits=c(0,0.17))+
1250
  geom_vline(xintercept = 1.5, color="black", size=0.25)+
1251
  geom_segment(data=data.frame(y=seq(1.5, 31.5,1)), inherit.aes = F, 
1252
               aes(y = y, yend = y, x=0.25, xend=2.8), color="white", size=0.25)+
1253
  geom_text(data = p.values, inherit.aes = F, aes(y=Name, x=2.8, label=round(p, 2)), size=2.5)+
1254
  coord_cartesian(clip = "off")+
1255
  ggtitle("CN gain")+
1256
  mytheme_1+
1257
  theme(strip.background = element_blank(),
1258
        strip.text = element_blank(),
1259
        axis.text.x = element_text(angle=45, hjust=1, size=7),
1260
        axis.ticks = element_blank(),
1261
        axis.text.y = element_text(size=7, margin = unit(c(0,-0.15,0,0), units = "cm")),
1262
        plot.margin = unit(units = "cm", c(0,1.25,0,0)),
1263
        axis.title = element_blank(),
1264
        panel.border = element_blank())+
1265
  labs(tag = "F")
1266
1267
```
1268
1269
### Copy number loss
1270
```{r copy number loss SF6}
1271
1272
df_loss <- df_snvs_chapuy %>% 
1273
  filter(Description=="CN loss") %>% 
1274
  mutate(value=factor(value, levels = c("0", "1", "2"), labels = c("wt", "loss", "loss"))) %>% 
1275
  group_by(Name, value) %>%
1276
  dplyr::summarise(MeanExhausted=mean(Exhausted/Absolute)) 
1277
1278
p.values <- df_snvs_chapuy %>% 
1279
  filter(Description=="CN loss") %>% 
1280
  mutate(Exhausted=Exhausted/Absolute) %>% 
1281
  mutate(value=factor(value, levels = c("0", "1", "2"), labels = c("wt", "loss", "loss"))) %>% 
1282
  compare_means(formula = Exhausted ~ value, group.by = "Name", p.adjust.method = "BH") %>% 
1283
  filter(p<0.05) %>% 
1284
  mutate(p=ifelse(p<0.005, 0.0051, p))
1285
1286
p7 <- df_loss %>% 
1287
  ggplot(aes(x=value, y=Name, fill=MeanExhausted))+
1288
  geom_tile()+
1289
  scale_fill_gradientn(name="Expression", colours = brewer.pal(5, "PRGn"), limits=c(0,0.17))+
1290
  geom_vline(xintercept = 1.5, color="black", size=0.25)+
1291
   geom_segment(data=data.frame(y=seq(1.5, 32.5,1)), inherit.aes = F, 
1292
               aes(y = y, yend = y, x=0.25, xend=2.8), color="white", size=0.25)+
1293
  geom_text(data = p.values, inherit.aes = F, aes(y=Name, x=2.8, label=round(p, 2)), size=2.5)+
1294
  ggtitle("CN loss")+
1295
    coord_cartesian(clip = "off")+
1296
  mytheme_1+
1297
  theme(strip.background = element_blank(),
1298
        strip.text = element_blank(),
1299
        axis.text.x = element_text(angle=45, hjust=1, size=7),
1300
        axis.ticks = element_blank(),
1301
        axis.text.y = element_text(size=7, margin = unit(c(0,-0.15,0,0), units = "cm")),
1302
        axis.title = element_blank(),
1303
        panel.border = element_blank())+
1304
  labs(tag = "G")
1305
1306
```
1307
1308
### Structural variants
1309
```{r structural variants SF6}
1310
1311
df_struct <- df_snvs_chapuy %>% 
1312
  filter(Description=="SV") %>% 
1313
  mutate(value=factor(value, levels = c("0", "3"), labels = c("wt", "mut")))%>% 
1314
   group_by(Name, value) %>%
1315
  dplyr::summarise(MeanExhausted=mean(Exhausted/Absolute)) 
1316
1317
p.values <- df_snvs_chapuy %>% 
1318
  filter(Description=="SV") %>% 
1319
  mutate(Exhausted=Exhausted/Absolute) %>% 
1320
   mutate(value=factor(value, levels = c("0", "3"), labels = c("wt", "mut"))) %>% 
1321
  compare_means(formula = Exhausted ~ value, group.by = "Name", p.adjust.method = "BH") %>% 
1322
  filter(p<0.05) 
1323
1324
p8 <- df_struct %>% 
1325
  ggplot(aes(x=value, y=Name, fill=MeanExhausted))+
1326
  geom_tile()+
1327
  scale_fill_gradientn(name="Expression", colours = brewer.pal(5, "PRGn"), limits=c(0,0.17))+
1328
  geom_vline(xintercept = 1.5, color="black", size=0.25)+
1329
  geom_segment(data=data.frame(y=seq(1.5, 7.5,1)), inherit.aes = F, 
1330
               aes(y = y, yend = y, x=0.25, xend=2.75), color="white", size=0.25)+
1331
  ggtitle("Structural variants")+
1332
  coord_cartesian(clip = "off")+
1333
  mytheme_1+
1334
  theme(strip.background = element_blank(),
1335
        strip.text = element_blank(),
1336
        axis.text.x = element_text(angle=45, hjust=1, size=7),
1337
        axis.ticks = element_blank(),
1338
        axis.text.y = element_text(size=7, margin = unit(c(0,-0.15,0,0), units = "cm")),
1339
        plot.margin = unit(units = "cm", c(0,1.25,0,0)),
1340
        axis.title = element_blank(),
1341
        panel.border = element_blank())+
1342
  labs(tag = "H")
1343
1344
```
1345
1346
1347
### Part 2
1348
```{r assemble plot SF6 part 2, fig.height=7}
1349
1350
p5+wrap_plots(p6/p8+plot_layout(heights = c(2,0.5)))+(p7/plot_spacer()+plot_layout(heights = c(2,0.5)))+
1351
  plot_layout(nrow = 1, widths = c(2.9,1,1))
1352
1353
#ggsave(width = 18, height = 14, units = "cm", filename = "SF6_p2.pdf")
1354
1355
```
1356
1357
### Part 3 (Legend)
1358
```{r assemble plot SF6 part 3, fig.height=1}
1359
1360
as_ggplot(get_legend(p8+guides(fill=guide_colorbar(nrow = 2, title = "Exhausted\nT-cells"))+
1361
                       theme(legend.position = "right",
1362
                             legend.key.height = unit(units = "cm", 0.3),
1363
                             legend.key.width = unit(units = "cm", 0.3))))
1364
1365
ggsave(width = 2, height = 2.4, units = "cm", filename = "SF6_legend.pdf")
1366
1367
```
1368
1369
# Supplementary Figure 7
1370
Panel A was generated using FlowJo. 
1371
1372
## Flow cytometry: IKZF3
1373
```{r, fig.height=3}
1374
1375
med <- df_ikzf3 %>% filter(Entity=="rLN") %>% pull(`FoxP3+/IKZF3+`) %>% median()
1376
1377
pvalues <- df_ikzf3 %>% rename(IKZF3=`FoxP3+/IKZF3+`) %>% 
1378
  data.frame() %>% 
1379
  compare_means(data=., formula = IKZF3 ~ Entity, ref.group = "rLN") %>% 
1380
  select(Entity=group2, p) %>% 
1381
  filter(p<0.05) %>% 
1382
  mutate(p=round(p,3))
1383
1384
nrow(df_ikzf3)
1385
1386
plot_aiolos <- df_ikzf3 %>% 
1387
  ggplot(aes(x=Entity,y=`FoxP3+/IKZF3+`))+
1388
  geom_hline(yintercept = med, size=0.25, linetype="dashed", color="grey60")+
1389
  geom_boxplot(width=0.5, outlier.alpha = 0, size=0.25)+
1390
  ggbeeswarm::geom_beeswarm(size=0.75, shape=21, stroke=0.25, cex = 2.25, aes(fill=Entity))+
1391
  geom_text(inherit.aes = F, data = pvalues %>% mutate(Y=c(75, 75)),
1392
            aes(x=Entity, y=Y, label=p), size=2.5, check_overlap = T)+
1393
  scale_fill_brewer(palette = "Paired", limits=c("DLBCL", "MCL", "FL", "MZL", "rLN"))+
1394
  scale_y_continuous(limits = c(0,80), name=expression('% IKZF3'^'+'~'of FoxP3'^'+'))+
1395
  scale_x_discrete(limits=c("rLN", "DLBCL", "MCL", "FL", "MZL"))+
1396
  ggtitle("Flow cytometry")+
1397
  mytheme_1+
1398
  theme(legend.position = "none",
1399
        strip.background = element_rect(color=NA),
1400
        axis.title.x = element_blank(),
1401
        plot.title = element_text(face = "plain", size=7),
1402
        panel.border = element_rect(size=0.5),
1403
        axis.text.x = element_text(angle=45, hjust = 1, size=7),
1404
        axis.text.y = element_text(size=7),
1405
        axis.title.y = element_text(size=7),
1406
        panel.background = element_rect(fill=NA),
1407
        plot.margin = unit(c(0,0.25,0,0.25), "cm"))
1408
1409
plot_spacer()+plot_aiolos+plot_layout(widths = c(3,1))
1410
1411
ggsave(width = 19, height = 5.7, units = "cm", filename = "SF7.pdf")
1412
1413
```
1414
1415
## Treg clonotypes
1416
```{r treg clonotypes SF7, fig.height=3}
1417
1418
df_clonotypes_shared <- 
1419
  left_join(DFtotal_5prime %>% filter(!is.na(raw_clonotype_id)) %>% 
1420
            select(Barcode_fulla=Barcode_full, PatientID, refUMAP_1a=refUMAP_1, refUMAP_2a=refUMAP_2, IdentIa=IdentI, raw_clonotype_id) %>% distinct(),
1421
          DFtotal_5prime %>% filter(!is.na(raw_clonotype_id)) %>% 
1422
            select(Barcode_fullb=Barcode_full, PatientID, refUMAP_1b=refUMAP_1, refUMAP_2b=refUMAP_2, IdentIb=IdentI, raw_clonotype_id) %>% distinct()
1423
          ) %>% 
1424
  filter(Barcode_fulla!=Barcode_fullb) %>% 
1425
  filter(IdentIa!=IdentIb)
1426
1427
treg_shared <- list()
1428
for(i in c(8,13,15)){
1429
1430
df_subset <- 
1431
  df_clonotypes_shared %>% 
1432
  add_entity() %>% 
1433
  filter(IdentIb==i) 
1434
1435
treg_shared[[i]] <- ggplot()+
1436
  geom_point_rast(data=DFtotal_5prime,
1437
                  aes(x=refUMAP_1, y=refUMAP_2, fill=IdentI), size=0.25, 
1438
                  alpha=ifelse(DFtotal_5prime$IdentI==i, 0.4, 0.04), stroke=0, shape=21)+
1439
  geom_curve(data= df_subset, 
1440
             aes(x=refUMAP_1a, y=refUMAP_2a, xend=refUMAP_1b, yend=refUMAP_2b, color=IdentIa,
1441
                 group=paste(raw_clonotype_id, PatientID)), curvature = -0.4, size=0.15, alpha=0.4)+
1442
  scale_color_manual(values = colors_umap_cl, limits=factor(cluster_order),
1443
                    labels=unlist(labels_cl), guide="none")+
1444
  scale_fill_manual(values = colors_umap_cl, limits=factor(cluster_order), guide="none",
1445
                    labels=unlist(labels_cl))+
1446
  guides(fill=guide_legend(nrow = 7, byrow = F, override.aes = list(size=1.75, stroke=0, shape=21, alpha=1, color="white")))+
1447
  coord_cartesian(clip = "off")+
1448
  xlab("refUMAP-1")+
1449
  ylab("refUMAP-2")+
1450
  mytheme_1+
1451
  theme(legend.position = "right",
1452
        panel.border = element_rect(size=0.25),
1453
        plot.title = element_textbox_simple(size=7, width = NULL, face = "plain",
1454
                                            padding = margin(1.25, 0, 1, 0),
1455
                                            lineheight = 1.25,
1456
                                            halign=0.5),
1457
        legend.text = element_text(size=7),
1458
        legend.spacing.x = unit("cm", x = 0.13),
1459
        axis.title.x = element_text(size=7),
1460
        axis.title.y = element_text(size=7),
1461
        axis.text = element_text(size=7),
1462
        legend.spacing.y = unit("cm", x = 0.001),
1463
        legend.key.width = unit("cm", x = 0.05),
1464
        legend.key.height = unit("cm", x = 0.5),
1465
        legend.box.margin = margin(unit = "cm",c(0,-0.35,0,-1)),
1466
        legend.title = element_blank())
1467
1468
if(i==8)
1469
  treg_shared[[i]] <- treg_shared[[i]]+
1470
  labs(title="Paired clonotypes of <span style='color:#C6DBEF'>T<sub>REG</sub> CM<sub>1</sub></span>",
1471
       tag = "C")
1472
  
1473
if(i==13)
1474
 treg_shared[[i]] <- treg_shared[[i]]+
1475
 labs(title="Paired clonotypes of <span style='color:#6BAED6'>T<sub>REG</sub> CM<sub>2</sub></span>")+
1476
  theme(axis.ticks.y = element_blank(),
1477
        axis.title.y = element_blank(),
1478
        axis.text.y = element_blank())
1479
1480
if(i==15)
1481
 treg_shared[[i]] <- treg_shared[[i]]+
1482
 labs(title="Paired clonotypes of <span style='color:#2171B5'>T<sub>REG</sub> EM<sub>1</sub></span>")+
1483
    theme(axis.ticks.y = element_blank(),
1484
        axis.title.y = element_blank(),
1485
        axis.text.y = element_blank())
1486
  
1487
}
1488
1489
plot_treg <- treg_shared[[8]]+treg_shared[[13]]+treg_shared[[15]]+plot_layout(guides = "collect")
1490
#plot_treg
1491
```
1492
1493
## Survival analysis
1494
```{r survival plots}
1495
1496
kmplot_tfh <- readRDS("data/SurvPlot_Tfh_Gallium.rds")
1497
kmplot_tfh$plot$plot_env$legend <- c(0.32, 0.2)
1498
kmplot_tfh$plot$theme$legend.position <- c(0.32, 0.2)
1499
kmplot_tfh$plot$theme$legend.background$fill <- NA
1500
kmplot_tfh$plot$theme$legend.text$colour <- NA
1501
kmplot_tfh$plot$theme$legend.text$size <- 7
1502
kmplot_tfh$plot <- kmplot_tfh$plot+annotation_custom(grob = textGrob(label = expression('T'[FH]~'High'), gp = gpar(cex=0.5), x=0.36, y=0.215))+
1503
  annotation_custom(grob = textGrob(label = expression('T'[FH]~'Low'), gp = gpar(cex=0.5), x=0.36, y=0.125))+
1504
  labs(tag = "D")
1505
1506
kmplot_treg <- readRDS("data/SurvPlot_TregEff2_Gallium.rds")
1507
kmplot_treg$plot$plot_env$legend <- c(0.32, 0.2)
1508
kmplot_treg$plot$theme$legend.position <- c(0.32, 0.2)
1509
kmplot_treg$plot$theme$legend.background$fill <- NA
1510
kmplot_treg$plot$theme$legend.text$colour <- NA
1511
kmplot_tfh$plot$theme$legend.text$size <- 7
1512
kmplot_treg$plot <- kmplot_treg$plot+annotation_custom(grob = textGrob(label = expression('T'[REG]~'EM'[2]~'High'), gp = gpar(cex=0.5), x=0.36, y=0.215))+
1513
  annotation_custom(grob = textGrob(label = expression('T'[REG]~'EM'[2]~'Low'), gp = gpar(cex=0.5), x=0.36, y=0.125))+
1514
  labs(tag = "E")
1515
1516
1517
```
1518
1519
## Assemble plot
1520
```{r}
1521
1522
plot_treg/
1523
  wrap_plots(kmplot_tfh$plot+kmplot_treg$plot+plot_spacer())+
1524
  plot_layout(heights = c(1.2,1))
1525
1526
#ggsave(width = 18, height = 11, units = "cm", filename = "SF7.pdf")
1527
1528
```
1529
1530
# Supplementary Figure 8
1531
## Dendrogram T-cells
1532
```{r dendrogram}
1533
1534
# Create data frame
1535
data <- data.frame(
1536
  level1="_Tcells",
1537
  level2=c("_'T'[Pr]",
1538
           rep("_'T'[H]",2),  
1539
           "_'T'[FH]", 
1540
           rep("_'T'[REG]",1),  
1541
           rep("_'T'[TOX]",3)),
1542
  level3=c("_'T'[Pr]", 
1543
           "TH_'CD4'^'+'*' Naive'",
1544
           "TH_'non-Naive (CM'[1]*' + CM'[2]*')'", 
1545
           "_'T'[FH]",  
1546
           "_'T'[REG]",
1547
           "TTOX_'CD8'^'+'*' Naive'",
1548
           "TTOX_'non-Naive (EM'[1]*' + EM'[2]*')'", 
1549
           "TTOX_'   Exhausted (EM'[3]*')'")
1550
)
1551
1552
# Data handling
1553
edges_level1_2 <- data %>% select(level1, level2) %>% unique %>% rename(from=level1, to=level2)
1554
edges_level2_3 <- data %>% select(level2, level3) %>% unique %>% rename(from=level2, to=level3)
1555
edge_list=rbind(edges_level1_2, edges_level2_3)
1556
vert <- data.frame(
1557
  name=unique(c(data$level1, data$level2, data$level3))) %>% 
1558
  mutate(cluster=as.character(c(NA, 14, 'TH', 6, 'TREG', "TTOX", 1, 2, 12, 3, 5))) %>% 
1559
  mutate(label=strsplit(name, split = "_") %>% sapply(., "[[", 2))
1560
1561
# Make ggraph object
1562
mygraph_codex <- graph_from_data_frame( edge_list ,vertices = vert)
1563
1564
# Small codex dendrogramm
1565
ggraph(mygraph_codex, layout = 'tree', circular = FALSE) + 
1566
  geom_edge_diagonal(strength = 1.4, edge_width=0.25)+
1567
  geom_node_label(aes(label=label), 
1568
                  parse = T, nudge_y=0.11, label.padding =  unit(units = "cm", 0.12),
1569
                  size=2.35, alpha=1, 
1570
                  fill=c(rep("white", 4), "black", rep("white", 6)), vjust=1, color=NA,
1571
                  label.size = 0, label.r = unit(units = "cm", 0))+
1572
  geom_node_text(aes(label=label, color=cluster), 
1573
                 vjust=1, nudge_y=0.05, 
1574
                 parse = T, 
1575
                 alpha=c(0,rep(1,5),rep(0,5)),
1576
                 size=2.35)+
1577
  scale_color_manual(values = colors_dendrogramm_codex)+
1578
  coord_cartesian(clip = "off")+
1579
  ggtitle("T-cell subsets \nidentified by mIF")+
1580
  theme_void()+
1581
  theme(legend.position = "none")+
1582
  theme(plot.margin = unit(c(-0.5,0.35,0.25,0.25), units = "cm"),
1583
        plot.title = element_text(hjust = 0.4, vjust=-7.5, size=7))
1584
1585
#ggsave(filename = "Figure8_p2.pdf", width = 12.6, height = 4.25, units = "cm")
1586
1587
```
1588
1589
## Handle data
1590
```{r handle data SF8}
1591
  
1592
# Read CODEX expression data
1593
# Available at BioStudies database (https://www.ebi.ac.uk/biostudies/) under accession number S-BIAD565
1594
codex_expression <- data.table::fread("data/cells_expression.csv") %>% tibble() %>% 
1595
  rename(unique_cell_id=V1)
1596
1597
proteins_selected <- c("PAX5", "CD20", "CD79a", "CD21", "PDPN", "CD38", "MCT",  "GRZB", "CD56", "CD163", "CD206", "CD11c",
1598
                       "CD15", "CD34", "CD31", "CD90", "Ki67", "PD1", "CXCR5", "ICOS", "CD69", "CD45RO", "TIM3", "LAG3",
1599
                       "CD57", "CD8", "CD45RA", "FOXP3", "CD4",  "CD3")
1600
1601
codex_meanExp <- codex_expression %>% 
1602
  left_join(., codex_annotation %>% select(unique_cell_id, Merged_final)) %>% 
1603
  filter(!is.na(Merged_final)) %>% 
1604
  select(-unique_cell_id) %>% 
1605
  group_by(Merged_final) %>% 
1606
  summarise_all(mean) %>% 
1607
  pivot_longer(cols = 2:ncol(.), names_to = "Protein", values_to = "Expression") %>% 
1608
  group_by(Protein) %>% 
1609
  mutate(Expression=(Expression-min(Expression))/(max(Expression)-min(Expression))) %>% 
1610
  filter(Protein %in% proteins_selected)
1611
1612
```
1613
1614
## Makers and cell types
1615
```{r plot markers SF8}
1616
1617
p2 <- codex_meanExp %>% 
1618
  ggplot(aes(x=Protein, y=Merged_final, fill=Expression))+
1619
  geom_tile()+
1620
  scale_fill_gradientn(name="Expression", colours = brewer.pal(5, "GnBu"), limits=c(0,1), breaks=c(0,0.5,1))+
1621
  geom_hline(yintercept = seq(1.5, 17.5, 1), size=0.25, color="white")+
1622
  geom_vline(xintercept = seq(1.5, 32.5, 1), size=0.25, color="white")+
1623
  scale_x_discrete( expand = c(0,0), limits=c(proteins_selected))+
1624
  scale_y_discrete(expand = c(0,0), limits=c("B", "FDC", "PC", "MC", "NK", "NKT",  "Macro", "DC", "Granulo", "Stromal cells",
1625
                                             "TPR", "TFH",  "TTOX_exh", "TTOX", "TTOXNaive",   "Treg",  "CD4T", "CD4TNaive"),
1626
                   labels=unlist(list("B-cells", "FDC", "Plasma cells", "Mast cells", "NK cells", "NK T-cells", "Macrophages", "Dendritic cells", "Granulocytes",
1627
                                      "Stromal cells", labels_codex$TPR, labels_codex$TFH, labels_codex$TTOX_exh, labels_codex$TTOX, labels_codex$TTOXNaive, 
1628
                                      labels_codex$Treg, labels_codex$CD4T, labels_codex$CD4TNaive)))+
1629
  guides(fill=guide_colorbar(ticks.colour = "black"))+
1630
  theme_bw()+
1631
  mytheme_1+
1632
   theme(axis.title = element_blank(),
1633
         legend.position = "top",
1634
         axis.text.y = element_text(size=7),
1635
         legend.text = element_text(size = 7, color="black"),
1636
         legend.title = element_text(size = 7, color="black", vjust = 0.8, margin = unit(units = "cm", c(0,0.2,0,0))),
1637
         legend.key.height = unit(0.25, "cm"),
1638
         plot.margin = unit(c(0,0,0,0), units = "cm"),
1639
         legend.key.width = unit(0.2, "cm"),
1640
         legend.box.spacing = unit(0.1, "cm"),
1641
         legend.box.margin = unit(c(0,0,0,0), units = "cm"),
1642
         plot.title = element_text(face = "plain", vjust = -1),
1643
         plot.tag = element_text(margin = unit(c(0,-0.5,-0.25,0), units = "cm")),
1644
         axis.text.x = element_text(size=6.5, angle = 45, hjust = 1))+
1645
  labs(tag = "C")
1646
1647
```
1648
1649
## T-cell numbers in codex
1650
```{r T-cell numbers SF8}
1651
1652
df_codex_no <- 
1653
  codex_annotation %>% 
1654
  filter(Merged_final %in% c("TTOXNaive", "TTOX_exh", "TTOX", "Treg", "TPR", "TFH", "CD4T", "CDT4Naive")) %>% 
1655
  count(PatientID, Merged_final, unique_region) %>% 
1656
  group_by(PatientID) %>% 
1657
  mutate(Sum=sum(n)) %>% 
1658
  ungroup() %>% 
1659
  mutate(No=dense_rank(desc(Sum)))
1660
1661
regions_random <- df_codex_no %>% 
1662
  select(PatientID, unique_region) %>% 
1663
  distinct() %>% 
1664
  group_by(PatientID) %>% 
1665
  sample_n(1)
1666
1667
p3 <- ggplot()+
1668
  geom_hline(yintercept = 47280, size=0.25, linetype="dashed")+
1669
  geom_bar(data=df_codex_no %>% filter(unique_region %in% regions_random$unique_region), 
1670
           aes(x=No-0.15, y=n, fill=Merged_final), color="white",
1671
           stat = "identity",  width=0.2, size=0.25, alpha=0.7)+
1672
  geom_bar(data=df_codex_no %>% filter(!unique_region %in% regions_random$unique_region), 
1673
           aes(x=No+0.15, y=n, fill=Merged_final), color="white",
1674
           stat = "identity",  width=0.25, size=0.25, alpha=0.7)+
1675
  scale_y_continuous(name = "Absolute number of cells - mIF", limits = c(0, 100000))+
1676
 scale_fill_manual(values = colors_codex[c(2:9)],
1677
                   limits=limits_codex[c(2:9)],
1678
                   labels=labels_codex[c(2:9)],
1679
                   name=NULL)+
1680
  guides(fill=guide_legend(nrow = 2, default.unit = "cm", override.aes = list(color="white"), 
1681
                           keywidth = 0.3, keyheight = 0.3, byrow = T))+
1682
  scale_x_continuous(name="Patients", 
1683
                     breaks=unique(df_codex_no$No), 
1684
                     labels=unique(df_codex_no$PatientID), 
1685
                     expand = c(0.02,0.02))+
1686
  mytheme_1+
1687
  theme(axis.text.x = element_text(angle = 45, hjust = 1),
1688
        plot.margin = unit(c(0,0,0,0), units = "cm"),
1689
        legend.box.margin = unit(c(0,0,-0.3,0), units = "cm"),
1690
        axis.title.y = element_text(size=7, vjust = -15),
1691
        axis.title.x = element_blank(),
1692
        legend.spacing.y = unit(0.15, units = "cm"),
1693
        plot.tag = element_text(margin = unit(c(0,-0.5,0,0), units = "cm")),
1694
        legend.position = "top")+
1695
  labs(tag = "D")
1696
1697
```
1698
1699
## Correlations
1700
```{r correlations SF8}
1701
1702
freq_codex <- 
1703
  codex_annotation %>% 
1704
  filter(Merged_final %in% c("TTOXNaive", "TTOX_exh", "TTOX", "Treg", "TPR", "TFH", "CD4T", "CD4TNaive")) %>% 
1705
  filter(!unique_region %in% c("191_1reg004", "191_4reg004", "191_4reg005", "191_1reg006")) %>% 
1706
  add_prop(vars = c("Merged_final", "PatientID"), group.vars = 2) %>% 
1707
  rename(Prop_codex=Prop, IdentI=Merged_final) 
1708
1709
freq_citeseq <- 
1710
  Combined_T@meta.data %>% 
1711
  add_prop(vars = c("IdentI", "PatientID"), group.vars = 2) %>% 
1712
  mutate(IdentII=case_when(IdentI==1 ~ "CD4TNaive",
1713
                           IdentI %in% c(2,9) ~ "CD4T",
1714
                           IdentI==14 ~ "TPR",
1715
                           IdentI==6 ~ "TFH",
1716
                           IdentI %in% c(8,11,13,15) ~ "Treg",
1717
                           IdentI==12 ~ "TTOXNaive",
1718
                           IdentI %in% c(3,16) ~ "TTOX",
1719
                           IdentI %in% c(5) ~ "TTOX_exh")) %>% 
1720
  group_by(IdentII, PatientID) %>% 
1721
  summarise(Prop=sum(Prop)) %>% 
1722
  rename(Prop_citeseq=Prop, IdentI=IdentII) %>% 
1723
  fill_zeros(names_from = "IdentI", values_from = "Prop_citeseq")
1724
1725
freq_joined <- left_join(freq_codex, freq_citeseq) %>% 
1726
  mutate(Prop_codex=100*Prop_codex, Prop_citeseq=100*Prop_citeseq)
1727
1728
this_theme <- 
1729
  theme_bw()+
1730
  mytheme_1+
1731
  theme(plot.margin = unit(c(0,0.2,0.2,0.35), units = "cm"),
1732
        axis.title.y = element_blank(),
1733
        axis.title.x = element_blank(),
1734
        plot.title = element_textbox_simple(face = "plain", halign=0.5, width = 2, padding = margin(0, 0, 0, 0)),
1735
        plot.tag = element_text(margin = unit(c(0,-0.5,0,0), units = "cm")),
1736
        axis.text = element_text(size=7, color="black"))
1737
1738
cor_plots_codex <- list()
1739
1740
cor_plots_codex[["TFH"]] <- 
1741
  freq_joined %>% 
1742
  filter(IdentI=="TFH") %>% 
1743
  ggplot(aes(x=Prop_codex, y=Prop_citeseq))+
1744
  geom_point(fill=colors_codex[["TFH"]], size=1, alpha=0.75, shape=21, stroke=0.1)+
1745
  geom_smooth(method = "lm", linetype="dashed", size=0.25, formula = y ~ x, na.rm = T,
1746
              color=colors_codex[["TFH"]], se=F, fullrange=T)+
1747
  stat_cor(aes(label=..r.label..), method = "pearson", size=2.5, label.x.npc = c(0.5), label.y.npc = c(0.1))+
1748
  scale_x_continuous(limits = c(0,40), breaks = c(0, 12, 24, 36), name = "mIF")+
1749
  scale_y_continuous(limits = c(0,40), breaks = c(0, 12, 24, 36), name = "CITE-seq")+
1750
  labs(title="T<sub>FH</sub>")+
1751
  coord_fixed()+
1752
  this_theme+
1753
  theme(plot.margin = unit(c(0,0,0.2,0), units = "cm"))
1754
1755
cor_plots_codex[["TREG"]] <- 
1756
  freq_joined %>% 
1757
  filter(IdentI=="Treg") %>% 
1758
  ggplot(aes(x=Prop_codex, y=Prop_citeseq))+
1759
  geom_point(fill=colors_codex[["Treg"]], size=1, alpha=0.75, shape=21, stroke=0.1)+
1760
  geom_smooth(method = "lm", linetype="dashed", size=0.25, formula = y ~ x, na.rm = T,
1761
              color="black", se=F, fullrange=T)+
1762
  stat_cor(aes(label=..r.label..), method = "pearson", size=2.5, label.x.npc = c(0.5), label.y.npc = c(0.1))+
1763
  scale_x_continuous(limits = c(0,56), breaks = c(0, 16, 32, 48), name = "mIF")+
1764
  scale_y_continuous(limits = c(0,56), breaks = c(0, 16, 32, 48), name = "CITE-seq")+
1765
  labs(title="T<sub>REG</sub>")+
1766
  coord_fixed()+
1767
  this_theme+
1768
  theme(axis.title.y = element_text(size=7, angle = 90, vjust = 2.5))
1769
1770
cor_plots_codex[["TTOXNaive"]] <- 
1771
  freq_joined %>% 
1772
  filter(IdentI=="TTOXNaive") %>% 
1773
  ggplot(aes(x=Prop_codex, y=Prop_citeseq))+
1774
  geom_point(fill=colors_codex[["TTOXNaive"]], size=1, alpha=0.75, shape=21, stroke=0.1)+
1775
  geom_smooth(method = "lm", linetype="dashed", size=0.25, formula = y ~ x, na.rm = T,
1776
              color=colors_codex[["TTOXNaive"]], se=F, fullrange=T)+
1777
  stat_cor(aes(label=..r.label..), method = "pearson", size=2.5, label.x.npc = c(0.5), label.y.npc = c(0.1))+
1778
  scale_x_continuous(limits = c(0,13), breaks = c(0, 4, 8, 12), name = "mIF")+
1779
  scale_y_continuous(limits = c(0,13), breaks = c(0, 4, 8, 12), name = "CITE-seq")+
1780
  labs(title="CD8<sup>+</sup> Naive")+
1781
  coord_fixed()+
1782
  this_theme+
1783
  theme(plot.margin = unit(c(0,0,0.2,0), units = "cm"))
1784
1785
cor_plots_codex[["THNaive"]] <- 
1786
  freq_joined %>% 
1787
  filter(IdentI=="CD4TNaive") %>% 
1788
  ggplot(aes(x=Prop_codex, y=Prop_citeseq))+
1789
  geom_point(fill=colors_codex[["CD4TNaive"]], size=1, alpha=0.75, shape=21, stroke=0.1)+
1790
  geom_smooth(method = "lm", linetype="dashed", size=0.25, formula = y ~ x, na.rm = T,
1791
              color=colors_codex[["CD4TNaive"]], se=F, fullrange=T)+
1792
  stat_cor(aes(label=..r.label..), method = "pearson", size=2.5, label.x.npc = c(0.53), label.y.npc = c(0.1))+
1793
  scale_x_continuous(limits = c(0,30), breaks = c(0, 10, 20, 30), name = "mIF")+
1794
  scale_y_continuous(limits = c(0,30), breaks = c(0, 10, 20, 30), name = "CITE-seq")+
1795
  labs(title="CD4<sup>+</sup> Naive")+
1796
  coord_fixed()+
1797
  this_theme+
1798
  theme(plot.title = element_textbox_simple(face = "plain", halign=0.5, margin = unit(units = "cm", c(0,0,-1.75,0)), 
1799
                                            width = 2, padding = margin(0, 0, 0, 0)),
1800
        plot.margin = unit(c(0,0,0.2,0), units = "cm"))
1801
1802
cor_plots_codex[["TPR"]] <- 
1803
  freq_joined %>% 
1804
  filter(IdentI=="TPR") %>% 
1805
  ggplot(aes(x=Prop_codex, y=Prop_citeseq))+
1806
  geom_point(fill=colors_codex[["TPR"]], size=1, alpha=0.75, shape=21, stroke=0.1)+
1807
  geom_smooth(method = "lm", linetype="dashed", size=0.25, formula = y ~ x, na.rm = T,
1808
              color=colors_codex[["TPR"]], se=F, fullrange=T)+
1809
  stat_cor(aes(label=..r.label..), method = "pearson", size=2.5, label.x.npc = c(0.5), label.y.npc = c(0.93))+
1810
  scale_x_continuous(limits = c(0,13), breaks = c(0, 4, 8, 12), name = "mIF")+
1811
  scale_y_continuous(limits = c(0,13), breaks = c(0, 4, 8, 12), name = "CITE-seq")+
1812
  labs(title="T<sub>Pr</sub>")+
1813
  coord_fixed()+
1814
  this_theme+
1815
  theme(axis.title.y = element_text(size=7, angle = 90, vjust = 2.5),
1816
        plot.title = element_textbox_simple(face = "plain", halign=0.5, margin = unit(units = "cm", c(0,0,-1.75,0)), 
1817
                                            width = 2, padding = margin(0, 0, 0, 0)),
1818
        plot.tag = element_text(margin = unit(c(0,0,-0.25,0), units = "cm")))
1819
1820
cor_plots_codex[["TH"]] <- 
1821
  freq_joined %>% 
1822
  filter(IdentI=="CD4T") %>% 
1823
  ggplot(aes(x=Prop_codex, y=Prop_citeseq))+
1824
  geom_point(fill=colors_codex[["CD4T"]], size=1, alpha=0.75, shape=21, stroke=0.1)+
1825
  geom_smooth(method = "lm", linetype="dashed", size=0.25, formula = y ~ x, na.rm = T,
1826
              color=colors_codex[["CD4T"]], se=F, fullrange=T)+
1827
  stat_cor(aes(label=..r.label..), method = "pearson", size=2.5, label.x.npc = c(0.5), label.y.npc = c(0.93))+
1828
  scale_x_continuous(limits = c(0,60), breaks = c(0, 20, 40, 60), name = "mIF")+
1829
  scale_y_continuous(limits = c(0,60), breaks = c(0, 20, 40, 60), name = "CITE-seq")+
1830
  labs(title="Memory T<sub>H</sub>")+
1831
  coord_fixed()+
1832
  this_theme+
1833
  theme(axis.title.y = element_text(size=7, angle = 90, vjust = 2.5))
1834
1835
cor_plots_codex[["TTOX"]] <- 
1836
  freq_joined %>% 
1837
  filter(IdentI=="TTOX") %>% 
1838
  ggplot(aes(x=Prop_codex, y=Prop_citeseq))+
1839
  geom_point(fill=colors_codex[["TTOX"]], size=1, alpha=0.75, shape=21, stroke=0.1)+
1840
  geom_smooth(method = "lm", linetype="dashed", size=0.25, formula = y ~ x, na.rm = T,
1841
              color=colors_codex[["TTOX"]], se=F, fullrange=T)+
1842
  stat_cor(aes(label=..r.label..), method = "pearson", size=2.5, label.x.npc = c(0.5), label.y.npc = c(0.1))+
1843
  scale_x_continuous(limits = c(0,45), breaks = c(0, 15, 30, 45), name = "mIF")+
1844
  scale_y_continuous(limits = c(0,45), breaks = c(0, 15, 30, 45), name = "CITE-seq")+
1845
  labs(title="Memory T<sub>TOX</sub>")+
1846
  coord_fixed()+
1847
  this_theme+
1848
  theme(axis.title.y = element_text(size=7, angle = 90, vjust = 2.5),
1849
        axis.title.x = element_text(size=7))
1850
1851
cor_plots_codex[["TTOX_exh"]] <- 
1852
  freq_joined %>% 
1853
  filter(IdentI=="TTOX_exh") %>% 
1854
  ggplot(aes(x=Prop_codex, y=Prop_citeseq))+
1855
  geom_point(fill=colors_codex[["TTOX_exh"]], size=1, alpha=0.75, shape=21, stroke=0.1)+
1856
  geom_smooth(method = "lm", linetype="dashed", size=0.25, formula = y ~ x, na.rm = T,
1857
              color=colors_codex[["TTOX_exh"]], se=F, fullrange=T)+
1858
  stat_cor(aes(label=..r.label..), method = "pearson", size=2.5, label.x.npc = c(0.5), label.y.npc = c(0.1))+
1859
  scale_x_continuous(limits = c(0,65), breaks = c(0, 20, 40, 60), name = "mIF")+
1860
  scale_y_continuous(limits = c(0,65), breaks = c(0, 20, 40, 60), name = "CITE-seq")+
1861
  labs(title="PD1<sup>+</sup> TIM3<sup>+</sup> T<sub>TOX</sub>")+
1862
  coord_fixed()+
1863
  this_theme+
1864
  theme(axis.title.x = element_text(size=7),
1865
        plot.margin = unit(c(0,0,0.2,0), units = "cm"))
1866
1867
freq_joined %>% 
1868
  group_by(IdentI) %>% 
1869
  summarise(R=cor.test(Prop_codex, Prop_citeseq)$estimate) %>% pull(R) %>% median()
1870
1871
```
1872
1873
## Assemble plot
1874
```{r assemble SF9, fig.height=5.5}
1875
1876
p_full <- wrap_plots(p2/p3+plot_layout(heights = c(1.25,1)))+wrap_plots(cor_plots_codex$TPR+labs(tag = "E")+cor_plots_codex$THNaive+cor_plots_codex$TH+cor_plots_codex$TFH+
1877
  cor_plots_codex$TREG+cor_plots_codex$TTOXNaive+cor_plots_codex$TTOX+cor_plots_codex$TTOX_exh+
1878
  plot_layout(ncol = 2))+
1879
  plot_layout(widths = c(2.25,1.15))
1880
p_full
1881
#ggsave(p_full, width = 18, height = 14, units = "cm", filename = "SF8.pdf")
1882
1883
1884
```
1885
1886
# Supplementary Figure 9
1887
## Immunofluorescence images
1888
```{r images SF9, fig.height=3}
1889
1890
plots_codex <- list()
1891
1892
for(r in c("191_3reg008", "191_4reg004", "191_2reg007", "191_5reg002", "191_1reg003", "empty")) {
1893
  
1894
  df_tmp <- codex_annotation %>% filter(unique_region== r) %>% 
1895
    mutate(Merged_all_simple=ifelse(Merged_final %in% c("Granulo", "Macro", "DC"), "Myeloid", Merged_final)) %>% 
1896
    mutate(Merged_all_simple=ifelse(Merged_all_simple %in% c("MC", "NKT", "PC", "NK"), "Other", Merged_all_simple)) %>% 
1897
    filter(((x-mean(.$x))^2+(y-mean(.$y))^2)<2500^2) 
1898
  
1899
  plots_codex[[r]] <- ggplot()+
1900
    geom_point_rast(data=df_tmp %>% filter(Merged_all_simple=="B"), aes(x=x,y=y), shape=21, size=0.25, stroke=0, alpha=1, raster.dpi =300,
1901
                    color=colors_codex[["B"]], fill=colors_codex[["B"]])+
1902
    geom_point_rast(data=df_tmp %>% filter(Merged_all_simple!="B"), aes(x=x,y=y, fill=Merged_all_simple, color=Merged_all_simple), 
1903
                    shape=21, size=0.25, stroke=0, alpha=1, raster.dpi=300)+
1904
    scale_color_manual(values = colors_codex, limits=limits_codex, labels=labels_codex, name="Cell type")+
1905
    scale_fill_manual(values = colors_codex, limits=limits_codex, labels=labels_codex, name="Cell type")+
1906
    ggtitle(unique(df_tmp$Entity))+
1907
    coord_fixed()+
1908
    theme_void()+
1909
    theme(legend.position = "none",
1910
          plot.title = element_text(color="white", hjust=0.1, size=8, 
1911
                                    margin = unit(units = "cm", c(0,0,-0.6,0)), face = "bold"),
1912
          plot.margin = unit(units = "cm", c(0.1, 0.1, 0.1, 0.1)),
1913
          panel.background = element_rect(fill = "black", color="black"))
1914
}
1915
1916
plots_codex
1917
1918
#ggsave(wrap_plots(plots_codex), width = 19, height = 12.5, units = "cm", filename = "SFigure9_p2.pdf")
1919
1920
legend_plot_codex <- ggplot()+
1921
  geom_point_rast(data=df_tmp %>% filter(Merged_all_simple!="B"), aes(x=x,y=y, fill=Merged_all_simple, color=Merged_all_simple), 
1922
                  shape=21, size=0.25, stroke=0, alpha=0, raster.dpi=300)+
1923
  scale_color_manual(values = colors_codex, limits=limits_codex, labels=labels_codex, name="Cell type")+
1924
  scale_fill_manual(values = colors_codex, limits=limits_codex, labels=labels_codex, name="Cell type")+
1925
  guides(fill=guide_legend(ncol = 2, override.aes = list(size=1.75, stroke=0, shape=21, alpha=1, color=NA)))+
1926
  guides(color=guide_legend(ncol = 2))+
1927
  ggtitle("")+
1928
  coord_fixed()+
1929
  mytheme_codex+
1930
  theme(panel.background = element_rect(fill = "black", color="black"),
1931
        legend.position = "right",
1932
        legend.text = element_text(size=6, color="white"),
1933
        legend.box.background = element_rect(fill = "black", color="black"),
1934
        legend.spacing.x = unit("cm", x = 0.13),
1935
        legend.spacing.y = unit("cm", x = 0.001),
1936
        legend.key.width = unit("cm", x = 0.05),
1937
        legend.key.height = unit("cm", x = 0.5),
1938
        legend.title = element_blank())
1939
1940
as_ggplot(get_legend(legend_plot_codex))
1941
#ggsave(width = 4, height = 4, units = "cm", filename = "SFigure9_p2_legend.pdf")
1942
1943
```
1944
1945
# Supplementary Figure 10
1946
## Load analysis
1947
```{r run analysis SF10}
1948
1949
# Read results from neighborhood analysis
1950
# Please run file: analysis/NeighborhoodAnalysis.Rmd
1951
load("output/Neighborhood_results.RData")
1952
1953
# Add codex annotation
1954
codex_annotation <- left_join(codex_annotation, nn_classes, by="unique_cell_id")
1955
codex_annotation
1956
1957
```
1958
1959
## Tissue cores
1960
### Images
1961
```{r plots SF10, fig.height=6}
1962
1963
regions <- codex_annotation %>% pull(unique_region) %>% unique()
1964
plots <- list()
1965
df <- list()
1966
for(r in regions){
1967
  
1968
df[[r]] <- codex_annotation %>% 
1969
  filter(!is.na(Region), unique_region %in% r) %>% 
1970
  filter(x>500, x<7500) %>% 
1971
  filter(y>500, y<7500) %>% 
1972
  filter(((x-mean(.$x))^2+(y-mean(.$y))^2)<2500^2)
1973
  
1974
plots[[r]] <- df[[r]] %>% 
1975
  ggplot()+
1976
  ggrastr::geom_point_rast(aes(x=x,y=y,color=Region, fill=Region), shape=21, size=0.25, stroke=0, alpha=1, raster.dpi =400)+
1977
  scale_color_manual(values = colors_nn)+
1978
  scale_fill_manual(values = colors_nn)+
1979
  guides(color=guide_legend(override.aes = list(size=3)))+
1980
  ggtitle(unique(df[[r]]$PatientID))+
1981
  coord_fixed(clip = "off")+
1982
  theme_void()+
1983
  theme(legend.position = "none",
1984
        plot.margin = unit(units = "cm", c(0.1,0.1,0.1,0.1)),
1985
        plot.subtitle = element_text(size=7, face = "bold", hjust=0.5, margin = unit(units = "cm", c(0,0,0,0))),
1986
        plot.title = element_text(size=6.5, face = "plain", margin = unit(units = "cm", c(-0.1,0,-0.6,-0.1))),
1987
        panel.background = element_rect(fill = NA, color = NA),
1988
        plot.background = element_rect(fill = NA, color = NA))
1989
1990
}
1991
1992
empty <- codex_annotation %>% 
1993
  filter(!is.na(Region), unique_region %in% "empty") %>% 
1994
  ggplot()+
1995
  ggrastr::geom_point_rast(aes(x=x,y=y,color=Region, fill=Region), alpha=0, raster.dpi =400)+
1996
  guides(color=guide_legend(override.aes = list(size=3, alpha=1)))+
1997
  ggtitle("")+
1998
  coord_fixed(clip = "off")+
1999
  theme_void()+
2000
  theme(legend.position = "right",
2001
        plot.margin = unit(units = "cm", c(0.1,0.1,0.1,0.1)),
2002
        plot.title = element_text(size=8, face = "plain", margin = unit(units = "cm", c(0,0,-0.75,0))),
2003
        panel.background = element_rect(fill = NA, color = NA),
2004
        plot.background = element_rect(fill = NA, color = NA))
2005
2006
2007
p_full <- 
2008
  wrap_plots(plots$`191_1reg006`+labs(tag = "A", subtitle = "rLN")+
2009
               plots$`191_3reg007`+
2010
               plots$`191_5reg005`+plot_layout(ncol = 1))+
2011
  
2012
  wrap_plots(plots$`191_4reg004`+labs(tag = "B",  subtitle = "DLBCL")+#
2013
               plots$`191_3reg001`+
2014
               plots$`191_4reg006`+plot_layout(ncol = 1))+
2015
  
2016
  wrap_plots(plots$`191_2reg007`+labs(tag = "C",  subtitle = "MCL")+
2017
               plots$`191_2reg002`+
2018
               plots$`191_3reg006`+plot_layout(ncol = 1))+
2019
  
2020
  wrap_plots(plots$`191_5reg002`+labs(tag = "D",  subtitle = "FL")+
2021
               plots$`191_3reg002`+
2022
               plots$`191_5reg001`+plot_layout(ncol = 1))+
2023
  
2024
  wrap_plots(plots$`191_1reg003`+labs(tag = "E",  subtitle = "MZL")+
2025
               plots$`191_1reg004`+
2026
               empty+plot_layout(ncol = 1))+
2027
  plot_layout(ncol = 5)
2028
2029
p_full
2030
2031
#ggsave(p_full, width = 18, height = 11.5, units = "cm", filename = "SF11.pdf")
2032
2033
```
2034
2035
### Legend
2036
```{r legend SF10, fig.height=1}
2037
2038
labels_nn <- c(
2039
  "N1: B-cells / FDC" ,
2040
  'N2: B-cells / FDC / T'[FH]~'',
2041
  'N3: T'[Pr]~'/ T'[REG]~'',
2042
  'N4: Macrophages / B-cells / Exh. T'[TOX]~'',
2043
  "N5: B-cells",
2044
  "N6: T-cell area I" ,
2045
  "N7: T-cell area II" ,
2046
  'N8: PC / NK / Memory T'[TOX]~'' ,
2047
  "N9: T-cell area III" ,
2048
  "N10: Stromal cells / Macrophages"
2049
   )
2050
2051
p_legend <- codex_annotation %>% 
2052
  filter(!is.na(Region), unique_region %in% r) %>% 
2053
  ggplot()+
2054
  ggrastr::geom_point_rast(aes(x=x,y=y,color=Region, fill=Region), shape=21, size=0.25, 
2055
                           stroke=0, alpha=1, raster.dpi =400)+
2056
  scale_color_manual(values = colors_nn, limits=factor(1:10), labels=labels_nn)+
2057
  scale_fill_manual(values = colors_nn, limits=factor(1:10), labels=labels_nn)+
2058
  guides(color=guide_legend(nrow = 2, override.aes = list(size=2, color="black", stroke=0.25)))+
2059
  ggtitle(unique(df[[r]]$PatientID))+
2060
  coord_fixed(clip = "off")+
2061
  theme_void()+
2062
  theme(legend.position = "right",
2063
        plot.margin = unit(units = "cm", c(0.1,0.1,0.1,0.1)),
2064
        legend.text = element_text(size=6.5),
2065
        legend.title = element_text(size=7, face = "bold"),
2066
        plot.subtitle = element_text(size=7, face = "bold", hjust=0.5, margin = unit(units = "cm", c(0,0,0,0))),
2067
        plot.title = element_text(size=6.5, face = "plain", margin = unit(units = "cm", c(-0.1,0,-0.6,-0.1))),
2068
        panel.background = element_rect(fill = NA, color = NA),
2069
        plot.background = element_rect(fill = NA, color = NA),
2070
        legend.box.margin = unit(c(0,0,0,-0.38), "cm"),
2071
        legend.key.width = unit("cm", x = 0.1),
2072
        legend.spacing.x = unit("cm", x = 0.1),
2073
        legend.key.height = unit("cm", x = 0.35))
2074
2075
as_ggplot(get_legend(p_legend))
2076
2077
#ggsave(width = 19, height = 1.5, units = "cm", filename = "SF11_legend.pdf")
2078
2079
```
2080
2081
## Composition of neighborhoods
2082
```{r neighborhood composition, fig.height=3}
2083
2084
df_freq_nh <- codex_annotation %>% 
2085
  add_prop(vars = c("Entity", "Region", "unique_region"), group.vars = 3) %>% 
2086
  fill_zeros(names_from = "Region", values_from = "Prop") %>%
2087
  group_by(Entity, Region) %>% 
2088
  mutate(Max=0.06+max(Prop),
2089
         Region_label=paste0("N", Region)) %>% 
2090
  mutate(Region_label=factor(Region_label, levels = paste0("N", 1:10))) %>% 
2091
  mutate(Max=ifelse(Region_label=="N8" & Entity=="MCL", 0.18, Max)) %>% 
2092
  ungroup()
2093
2094
pvalues <- df_freq_nh %>% 
2095
  compare_means(data=., formula = Prop ~ Entity, ref.group = "rLN", 
2096
                group.by = "Region_label", p.adjust.method = "BH") %>% 
2097
  filter(p.adj<0.05) %>% 
2098
  mutate(p.adj_s=format(p.adj, scientific = TRUE, digits=1)) %>% 
2099
  mutate(p.adj_f=case_when(p.adj > 0.01 ~ as.character(round(p.adj, 2)),
2100
                           p.adj==0.01 ~ "0.01",
2101
                           p.adj < 0.01 ~ p.adj_s),
2102
         Entity=group2) %>% 
2103
  mutate(Entity=factor(Entity, levels = c("rLN", "DLBCL", "MCL", "FL", "MZL"))) %>% 
2104
  left_join(., df_freq_nh %>% select(Region_label, Max, Entity) %>% distinct, by = c("Region_label", "Entity"))
2105
2106
df_medianLines <- df_freq_nh %>% 
2107
  filter(Entity=="rLN") %>% 
2108
  group_by(Region_label) %>% 
2109
  dplyr::summarise(MedianProp=median(Prop)) 
2110
2111
df_freq_nh %>% 
2112
  ggplot(aes(x=Entity, y=Prop)) +
2113
  geom_hline(data=df_medianLines, aes(yintercept=MedianProp),
2114
             size=0.25, linetype="dashed", color="grey60")+
2115
  geom_boxplot(width=0.5, outlier.alpha = 0, size=0.25)+
2116
  ggbeeswarm::geom_beeswarm(size=1, shape=21, stroke=0.1, cex = 2, aes(fill=Region))+
2117
  geom_text(data=pvalues, inherit.aes = F, aes(y=Max, x=Entity, label=p.adj_f), size=2.5)+
2118
  scale_fill_manual(values = colors_nn)+
2119
  scale_x_discrete(limits=c("rLN", "DLBCL", "MCL", "FL", "MZL"))+
2120
  facet_wrap(~Region_label, strip.position = "top", scales = "free_y", nrow = 2)+
2121
  scale_y_continuous(name = "% of total area", expand = c(0,0.075))+
2122
  mytheme_1+
2123
  theme(strip.text.y = element_text(angle = 0, size=6),
2124
        axis.text.x = element_text(angle=45, hjust=1),
2125
        axis.title.x = element_blank(),
2126
        strip.background = element_blank(),
2127
        plot.margin = unit(c(0,0.1,0,0.1), "cm"))+
2128
  labs(tag = "F")
2129
2130
ggsave(width = 18, height = 7, units = "cm", filename = "SF10.pdf")
2131
2132
```
2133
2134
# Session info
2135
```{r session}
2136
2137
sessionInfo()
2138
2139
```