Figure 4

Read data, functions and packages

source("R/ReadPackages.R")
source("R/Functions.R")
source("R/ReadData.R")
source("R/ThemesColors.R")
source("R/Helpers.R")

Clonotypes projected onto UMAP

set.seed(1)
df_clonotypes <- 
  DFtotal_5prime %>% 
  filter(!is.na(raw_clonotype_id)) %>% 
  select(Barcode_full, PatientID, refUMAP_1, refUMAP_2, Entity, IdentI, raw_clonotype_id) %>% 
  distinct() %>% 
  add_count(IdentI, PatientID, raw_clonotype_id) %>% ungroup() %>% 
  select(-Barcode_full) %>% 
  group_by(PatientID, raw_clonotype_id, IdentI) %>% 
  summarise(refUMAP_1=median(refUMAP_1), refUMAP_2=median(refUMAP_2), n, Entity, .groups = "drop") %>% 
  distinct() %>% 
  #mutate(n=ifelse(n>50, 50, n)) %>% 
  mutate(Entity=factor(Entity, levels=c("rLN", "DLBCL", "MCL", "FL", "MZL")))
  
DF_5prime_umap <- DFtotal_5prime %>% 
  select(refUMAP_1, refUMAP_2, IdentI, Entity, PatientID) %>% 
  distinct() %>% 
  mutate(Entity=factor(Entity, levels=c("rLN", "DLBCL", "MCL", "FL", "MZL")))

df_clonotypes_subset <- list()

# Filter clonotypes to avoud overplotting
w <- 30
#for(e in entities){
  for(i in c(3,5,6)){
    for(p in unique(df_clonotypes$PatientID)){
        tmp <- df_clonotypes %>% 
          filter(n>2, IdentI==i, PatientID==p) 
        
        if(nrow(tmp)>w){
          
          df_clonotypes_subset[[paste0(i, p)]] <- tmp %>% sample_n(size = w)
          
          } else {
            df_clonotypes_subset[[paste0(i, p)]] <- tmp
          }
        
      }
    }
#  }
rm(w,p)

df_clonotypes_subset <- bind_rows(df_clonotypes_subset) %>% 
  rbind(df_clonotypes %>% filter(n>2, !IdentI %in% c(3,5,6)),
        .)

p1 <- ggplot()+
  geom_point_rast(data=DF_5prime_umap %>% select(-Entity), aes(x=refUMAP_1, y=refUMAP_2), 
                  size=0.2, alpha=0.2, stroke=0, shape=21,  fill="grey90")+
  geom_point_rast(data=DF_5prime_umap, aes(x=refUMAP_1, y=refUMAP_2, fill=IdentI), size=0.2, 
                  alpha=ifelse(DF_5prime_umap$IdentI %in% c("6", "3", "5", "11", "14"), 0.04, 0.2), 
                  stroke=0, shape=21)+
  geom_point(data=df_clonotypes_subset, aes(x=refUMAP_1, y=refUMAP_2, size=n, color=IdentI), shape=21, stroke=0.25,
             alpha=ifelse(df_clonotypes_subset$Entity %in% c("FL", "MZL"), 1, 0.75))+
  scale_color_manual(values = colors_umap_cl, guide="none")+
  scale_fill_manual(values = colors_umap_cl, guide="none")+
  scale_size_continuous(range=c(1, 5), limits=c(3, 50), breaks=c(3, 20, 35, 50),
                        labels=c("3", "20", "35", "> 50"), name = NULL)+
  facet_wrap(~Entity, nrow = 1)+
  geom_text(data = df_clonotypes %>% select(PatientID, Entity) %>% distinct() %>% add_count(Entity), aes(label = paste0("n = ", n)),
            x = 9.65, y = -6.9, hjust=1, check_overlap = T, size=2.5)+
  xlab("refUMAP-1")+
  ylab("refUMAP-2")+
  mytheme_1+
  theme(legend.position = "top",
        legend.text = element_text(size=7),
        legend.background = element_rect(fill=NA),
        legend.box = unit("cm", x = 0.01),
        legend.spacing.x = unit("cm", x = 0.05),
        legend.spacing.y = unit("cm", x = 0.001),
        panel.border = element_rect(size=0.25, color="black"),
        legend.box.spacing = unit(0, units = "cm"),
        strip.background = element_rect(size=0.25),
        legend.box.margin = unit(c(0,-12.5,-0.1,0), units = "cm"))+
  labs(tag = "A")

p1

Quantification of clonotypes

df_clon_sign <- df_clonotypes %>% mutate(isClonal=ifelse(n>1, "clonal", "not")) %>% 
  group_by(isClonal, PatientID, IdentI) %>% 
  summarise(Total=sum(n)) %>% 
  fill_zeros(names_from = "IdentI", values_from = "Total") %>% 
  pivot_wider(names_from = "isClonal", values_from = "Total") %>% 
  mutate(Prop=round(clonal/(not+clonal), 2)) %>% 
  add_entity() %>% 
  filter(IdentI %in% c("5", "3", "6", "11")) %>% 
  mutate(Entity=factor(Entity, levels = c("rLN", "DLBCL", "MCL", "FL", "MZL"))) %>% 
  mutate(Prop=ifelse(is.nan(Prop), 0, Prop)) %>% 
  ungroup() %>% 
  mutate(IdentI=factor(IdentI, levels=cluster_order)) %>% 
  mutate(Label=factor(IdentI, levels=cluster_order, labels = labels_cl_parsed[as.character(cluster_order)]))

df_clon_sign_p <- 
  df_clon_sign %>% 
  mutate(Entity=as.factor(Entity)) %>% 
  mutate(Prop=Prop+sample(seq(0.01, 0.03, 0.0001), 17)) %>% 
  group_by(IdentI) %>% 
  wilcox_test(data=., formula = Prop ~ Entity, ref.group = "rLN", alternative = "less") %>% 
  select(IdentI, Entity=group2, p) %>% 
  mutate(Entity=factor(Entity, levels = c("rLN", "DLBCL", "MCL", "FL", "MZL"))) %>% 
  mutate(p=ifelse(p>0.05, NA, p)) %>% 
  filter(!is.na(p)) %>% 
  left_join(., data.frame(IdentI=factor(c(5,6,11)), height=c(106, 62.5, 50)))

p <- list()

for(i in c(1:4)){
  
  y <- list(c(3),c(5),c(6),c(11))[[i]]
  ylim <- c(65, 125, 75, 58)
  
  p[[i]] <- df_clon_sign %>% 
  filter(IdentI %in% y) %>% 
  ggplot(aes(x=Entity, y=100*Prop, fill=IdentI))+
  ggbeeswarm::geom_beeswarm(cex = 3.5, stroke=0.25, groupOnX = TRUE, shape = 21, size = 1.25,  alpha = 1, color="white")+
  #geom_text(data=df_clon_sign_p %>% filter(IdentI %in% y), inherit.aes = F, aes(y=height, x=Entity, label=p), hjust=0.1, size=2.25, angle=45)+
  geom_text(data=df_clon_sign_p %>% filter(IdentI %in% y), inherit.aes = F, aes(y=height, x=Entity, label=p), hjust=0.2, size=2.5, angle=45)+
  scale_color_manual(values = colors_umap_cl, guide="none")+
  scale_fill_manual(values = colors_umap_cl, guide="none")+
  ylab("Cell number")+
  scale_y_continuous(name="% of clontypes of size > 1", limits=c(0,ylim[i]))+
  scale_x_discrete(expand = c(0.17,0.17))+
  facet_wrap(~Label, ncol = 2, labeller = label_parsed)+
  mytheme_1+
  theme(axis.title.x = element_blank(),
        strip.background = element_rect(color=NA),
        plot.margin = unit(c(0.1, 0.2, 0, 0), units = "cm"),
        panel.border = element_rect(size = 0.5),
        axis.text.x = element_text(angle=45, hjust = 1))
  
  if(i!=1){
    p[[i]] <- p[[i]]+
      theme(axis.title.y = element_blank()
            )
  }
  
  if(i==1){
    p[[i]] <- p[[i]]+
      labs(tag = "B")
  }
  
  if(i!=4){
    p[[i]] <- p[[i]]+theme(
      plot.margin = unit(c(0.1, 0.5, 0, 0), units = "cm"))
  }
  
}

wrap_plots(p, nrow = 1)

#ggsave(width = 16, height = 5, units = "cm", filename = "ResponseFigure4.pdf")

Shared clonotypes

df_clonotypes_shared <- 
  left_join(DFtotal_5prime %>% filter(!is.na(raw_clonotype_id)) %>% 
            select(Barcode_fulla=Barcode_full, PatientID, refUMAP_1a=refUMAP_1, refUMAP_2a=refUMAP_2, IdentIa=IdentI, raw_clonotype_id) %>% distinct(),
          DFtotal_5prime %>% filter(!is.na(raw_clonotype_id)) %>% 
            select(Barcode_fullb=Barcode_full, PatientID, refUMAP_1b=refUMAP_1, refUMAP_2b=refUMAP_2, IdentIb=IdentI, raw_clonotype_id) %>% distinct()
          ) %>% 
  filter(Barcode_fulla!=Barcode_fullb) %>% 
  filter(IdentIa!=IdentIb)

df_clonotypes_shared_subset <- 
  df_clonotypes_shared %>% 
  add_entity() %>% 
  mutate(Entity=factor(Entity, levels=c("rLN", "DLBCL", "MCL", "FL", "MZL"))) %>% 
  filter(PatientID %in% c("LN0132", "LN0302", "LN0193", "LN0198", "LN0078")) %>% 
  filter(IdentIa==14)  %>% 
  mutate(Ident_shared=ifelse(IdentIa==14, IdentIb, IdentIa))

p2 <- ggplot()+
  geom_point_rast(data=DF_5prime_umap %>% select(-Entity), aes(x=refUMAP_1, y=refUMAP_2), 
                  size=0.2, alpha=0.2, stroke=0, shape=21, fill="grey90")+
  geom_point_rast(data=DF_5prime_umap %>% 
                    filter(PatientID %in% c("LN0132", "LN0302", "LN0193", "LN0198", "LN0078")) %>% 
                    mutate(PatientID_new=paste0(PatientID, " (", Entity, ")")),
                  aes(x=refUMAP_1, y=refUMAP_2, fill=IdentI), size=0.25, alpha=0.5, stroke=0, shape=21)+
  geom_curve(data= df_clonotypes_shared_subset,
             aes(x=refUMAP_1a, y=refUMAP_2a, xend=refUMAP_1b, yend=refUMAP_2b, color=Ident_shared,
                 group=paste(raw_clonotype_id, PatientID)), size=0.15, alpha=0.2, curvature = 0.3)+
  scale_fill_manual(values = colors_umap_cl, guide="none")+
  scale_color_manual(values = colors_umap_cl, guide="none")+
  facet_wrap(~Entity, nrow = 1)+
  geom_text(data = data.frame(PatientID=c("LN0132", "LN0302", "LN0193", "LN0198", "LN0078")) %>% 
              add_entity() %>% 
              mutate(Entity=factor(Entity, levels=c("rLN", "DLBCL", "MCL", "FL", "MZL"))), aes(label = PatientID), 
            x = 9.65, y = -6.9, hjust=1, check_overlap = T, size=2.5)+
  xlab("refUMAP-1")+
  ylab("refUMAP-2")+
  ggtitle(expression('Pairs of identical clonotypes between T'[Pr]~'and other T-cell subsets'))+
  mytheme_1+
  theme(legend.position = "none",
        strip.background = element_rect(size=0.25),
        panel.border = element_rect(size=0.25, color="black"))+
  labs(tag = "C")

p2

Additional legend

p_legend <- 
  df_comb %>% 
  sample_n(100) %>% 
  ggplot(aes(x=wnnUMAP_1, y=wnnUMAP_2, color=as.factor(IdentI), fill=as.factor(IdentI)))+
  geom_point(size=2.25, stroke=0, shape=21, alpha=1)+
  scale_color_manual(values = colors_umap_cl, limits=factor(cluster_order), labels=unlist(labels_cl))+
  scale_fill_manual(values = colors_umap_cl, limits=factor(cluster_order), labels=unlist(labels_cl))+
  guides(fill=guide_legend(nrow = 2, byrow = T))+
  guides(color=guide_legend(nrow = 2, byrow = T))+
  coord_fixed(clip = "off")+
  mytheme_1+
  theme_void()+
  theme(legend.position = "top",
        legend.text = element_text(size=7.2, margin = unit(units = "cm", x = c(0,0,0,-0.3))),
        legend.spacing.x = unit("cm", x = 0.42),
        legend.spacing.y = unit("cm", x = 0.001),
        legend.key.width = unit("cm", x = 0.055),
        legend.key.height = unit("cm", x = 0.5),
        legend.box.spacing = unit(0, units = "cm"),
        legend.title = element_blank())

as_ggplot(get_legend(p_legend))

#ggsave(as_ggplot(get_legend(p_legend)), width = 13, height = 1, units = "cm", filename = "Figure4_legend.pdf")

Compose

p_full <- p1/wrap_plots(p[[1]], p[[2]], p[[3]], p[[4]], nrow = 1)/p2
#ggsave(p_full, width = 18.5, height = 16.75, units = "cm", filename = "Figure4.pdf")

Session info

sessionInfo()
## R version 4.1.2 (2021-11-01)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Rocky Linux 8.8 (Green Obsidian)
## 
## Matrix products: default
## BLAS/LAPACK: /g/easybuild/x86_64/Rocky/8/haswell/software/FlexiBLAS/3.0.4-GCC-11.2.0/lib64/libflexiblas.so.3.0
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
##  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8    LC_PAPER=en_US.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C             LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] grid      stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] pamr_1.56.1        cluster_2.1.2      glmnet_4.1-2       Matrix_1.5-1       immunarch_0.7.0    data.table_1.14.2 
##  [7] dtplyr_1.2.2       rmdformats_1.0.4   ggplotify_0.1.0    ggraph_2.0.6       igraph_1.3.5       ggrastr_1.0.1     
## [13] ggtext_0.1.1       ggalluvial_0.12.3  maxstat_0.7-25     survival_3.2-13    survminer_0.4.9    ggridges_0.5.3    
## [19] cowplot_1.1.1      R.utils_2.11.0     R.oo_1.24.0        R.methodsS3_1.8.1  readxl_1.4.1       caret_6.0-90      
## [25] lattice_0.20-45    patchwork_1.1.2    rstatix_0.7.0      ggpubr_0.4.0       ggrepel_0.9.1      matrixStats_0.61.0
## [31] scales_1.2.1       RColorBrewer_1.1-3 viridis_0.6.2      viridisLite_0.4.1  forcats_0.5.1      stringr_1.4.1     
## [37] dplyr_1.0.10       purrr_0.3.4        readr_2.1.2        tidyr_1.2.1        tibble_3.1.8       ggplot2_3.3.6     
## [43] tidyverse_1.3.1    SeuratObject_4.0.4 Seurat_4.1.0       knitr_1.40        
## 
## loaded via a namespace (and not attached):
##   [1] scattermore_0.8       prabclus_2.3-2        ModelMetrics_1.2.2.2  exactRankTests_0.8-34 bit64_4.0.5          
##   [6] irlba_2.3.5           rpart_4.1-15          doParallel_1.0.17     generics_0.1.3        RANN_2.6.1           
##  [11] future_1.23.0         bit_4.0.4             tzdb_0.3.0            rlist_0.4.6.2         spatstat.data_2.1-2  
##  [16] xml2_1.3.2            lubridate_1.8.0       httpuv_1.6.6          assertthat_0.2.1      gower_0.2.2          
##  [21] xfun_0.33             hms_1.1.2             jquerylib_0.1.4       evaluate_0.16         promises_1.2.0.1     
##  [26] DEoptimR_1.0-11       fansi_1.0.3           dbplyr_2.1.1          km.ci_0.5-2           DBI_1.1.2            
##  [31] htmlwidgets_1.5.4     spatstat.geom_2.3-2   stringdist_0.9.8      stats4_4.1.2          ellipsis_0.3.2       
##  [36] backports_1.4.1       bookdown_0.29         deldir_1.0-6          vctrs_0.4.2           Cairo_1.5-12.2       
##  [41] ROCR_1.0-11           abind_1.4-5           cachem_1.0.6          withr_2.5.0           ggforce_0.4.0        
##  [46] robustbase_0.95-0     vroom_1.5.7           sctransform_0.3.3     mclust_5.4.10         goftest_1.2-3        
##  [51] ape_5.6-2             lazyeval_0.2.2        crayon_1.5.2          labeling_0.4.2        recipes_0.1.17       
##  [56] pkgconfig_2.0.3       tweenr_2.0.2          nlme_3.1-153          vipor_0.4.5           nnet_7.3-16          
##  [61] rlang_1.0.6           globals_0.14.0        diptest_0.76-0        lifecycle_1.0.2       miniUI_0.1.1.1       
##  [66] modelr_0.1.8          cellranger_1.1.0      polyclip_1.10-0       lmtest_0.9-39         phangorn_2.10.0      
##  [71] ggseqlogo_0.1         KMsurv_0.1-5          carData_3.0-5         zoo_1.8-9             reprex_2.0.1         
##  [76] beeswarm_0.4.0        GlobalOptions_0.1.2   pheatmap_1.0.12       png_0.1-7             KernSmooth_2.23-20   
##  [81] pROC_1.18.0           shape_1.4.6           parallelly_1.30.0     spatstat.random_2.1-0 gridGraphics_0.5-1   
##  [86] ggsignif_0.6.3        magrittr_2.0.3        plyr_1.8.7            ica_1.0-2             compiler_4.1.2       
##  [91] factoextra_1.0.7      fitdistrplus_1.1-6    cli_3.4.1             listenv_0.8.0         pbapply_1.5-0        
##  [96] MASS_7.3-54           mgcv_1.8-38           tidyselect_1.1.2      stringi_1.7.8         highr_0.9            
## [101] yaml_2.3.5            survMisc_0.5.5        sass_0.4.2            fastmatch_1.1-3       tools_4.1.2          
## [106] future.apply_1.8.1    parallel_4.1.2        circlize_0.4.15       rstudioapi_0.13       uuid_1.1-0           
## [111] foreach_1.5.2         gridExtra_2.3         prodlim_2019.11.13    farver_2.1.1          Rtsne_0.16           
## [116] digest_0.6.29         shiny_1.7.2           lava_1.6.10           quadprog_1.5-8        fpc_2.2-9            
## [121] Rcpp_1.0.9            gridtext_0.1.4        car_3.1-0             broom_1.0.1           later_1.3.0          
## [126] RcppAnnoy_0.0.19      httr_1.4.2            kernlab_0.9-31        colorspace_2.0-3      rvest_1.0.2          
## [131] fs_1.5.2              tensor_1.5            reticulate_1.24       splines_4.1.2         uwot_0.1.11          
## [136] yulab.utils_0.0.4     spatstat.utils_2.3-0  graphlayouts_0.8.2    xgboost_1.4.1.1       shinythemes_1.2.0    
## [141] flexmix_2.3-18        plotly_4.10.0         xtable_1.8-4          jsonlite_1.8.0        tidygraph_1.2.2      
## [146] timeDate_3043.102     UpSetR_1.4.0          modeltools_0.2-23     ipred_0.9-12          R6_2.5.1             
## [151] pillar_1.8.1          htmltools_0.5.3       mime_0.12             glue_1.6.1            fastmap_1.1.0        
## [156] class_7.3-19          codetools_0.2-18      mvtnorm_1.1-3         utf8_1.2.2            bslib_0.4.0          
## [161] spatstat.sparse_2.1-0 ggbeeswarm_0.6.0      leiden_0.3.9          rmarkdown_2.17        munsell_0.5.0        
## [166] iterators_1.0.14      haven_2.4.3           reshape2_1.4.4        gtable_0.3.1          spatstat.core_2.4-0