Figure 1

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")

UMAP plot

# Fine tuning for labels
median_umap <- df_comb %>% 
  group_by(IdentI) %>% 
  summarise(Median1=median(wnnUMAP_1), Median2=median(wnnUMAP_2)) %>% 
  mutate(Code=ifelse(IdentI %in% c(15, 18, 11, 6, 4), T, F)) %>% 
  mutate(Median2=ifelse(IdentI %in% 6, Median2+0.5, Median2)) %>% 
  mutate(Median2=ifelse(IdentI %in% 9, Median2+0.75, Median2)) %>% 
  mutate(Median1=ifelse(IdentI %in% 9, Median1-1, Median1)) %>% 
  mutate(Median2=ifelse(IdentI %in% 14, Median2+0.6, Median2)) %>% 
  mutate(Median1=ifelse(IdentI %in% 14, Median1-1.75, Median1)) %>% 
  mutate(IdentI=factor(IdentI, levels = cluster_order)) %>% 
  left_join(., data.frame(IdentI=factor(cluster_order), IdentI_label=seq(1:14)))

# Set origin for 'frameless' umap
ori <- c(-8.25,-8.5)
l <- 3
off <- 1

plot_umap <- df_comb %>% 
  ggplot(aes(x=wnnUMAP_1, y=wnnUMAP_2, fill=as.factor(IdentI)))+
  ggrastr::geom_point_rast(size=0.35, stroke=0, shape=21, raster.dpi = 200, alpha=0.75)+
  geom_text(data=median_umap, aes(x=Median1, color=Code, y=Median2, label=paste0("C", IdentI_label)), 
            size=2.5, fontface="bold")+
  scale_color_manual(values = c("black", "grey96"), guide="none")+
  scale_fill_manual(values = colors_umap_cl, limits=factor(cluster_order), labels=unlist(labels_cl))+
  scale_x_continuous(limits = c(ori[1],10), expand = c(0,0))+
  scale_y_continuous(limits = c(ori[2],10), expand = c(0,0))+
  annotation_custom(grob = linesGrob(gp=gpar(fill="black", lex=0.25), 
                                     arrow = arrow(ends = "last", type="closed", length=unit(0.15, "cm"))), 
                    xmin = ori[1]+off, xmax = ori[1]+off+l, ymin=ori[2]+off, ymax=ori[2]+off)+
  annotation_custom(grob = linesGrob(gp=gpar(fill="black", lex=0.25), 
                                     arrow = arrow(ends = "last", type="closed", length=unit(0.15, "cm"))), 
                    ymin = ori[2]+off, ymax = ori[2]+off+l, xmin=ori[1]+off, xmax=ori[1]+off)+
  annotation_custom(grob = textGrob(label = "wnnUMAP-1", gp = gpar(cex=0.6)), 
                    xmin = ori[1]+off+l/2, xmax = ori[1]+off+l/2, ymin=ori[2]+off/3, ymax=ori[2]+off/3)+
  annotation_custom(grob = textGrob(label = "wnnUMAP-2", gp = gpar(cex=0.6), rot = 90), 
                    xmin=ori[1]+off/3, xmax=ori[1]+off/3, ymin=ori[2]+off+l/2, ymax=ori[2]+off+l/2)+
    
  coord_fixed(clip = "off")+
  theme_void()+
  theme(legend.position = "none")

plot_umap

#ggsave(plot_umap, filename = "Figure1_p1.pdf", width = 8.25, height = 7.25, units = "cm")

Gene expression

Selected genes

genes_selected <- 
  c("MKI67",
    "CCR7", 
    "KLF2",
    "TCF7", 
    "TOX",
    "TOX2", 
    "ASCL2",
    "FOXP3", 
    "IKZF3",
    "GZMA", 
    "GZMK", 
    "CCL5", 
    "NKG7")

Plot

DefaultAssay(Combined_T) <- "integratedRNA"

perc_expr <- 
  FetchData(Combined_T, slot = "counts", vars = c("IdentI", paste0("rna_", genes_selected))) %>% 
  mutate(IdentI=as.factor(IdentI)) %>% 
  mutate_if(.predicate = is.numeric, .funs = ~ifelse(isZero(.), 1, 0)) %>% 
  pivot_longer(cols = 2:ncol(.), names_to = "Gene") %>% 
  group_by(IdentI, Gene) %>% 
  count(value) %>% 
  mutate(Prop=n/sum(n)) %>% 
  filter(value==0) %>% 
  select(-value, -n) %>% 
  mutate(Gene=substr(Gene, 5, nchar(.)))

DefaultAssay(Combined_T) <- "integratedRNA"

plot_genex <- 
  FetchData(Combined_T, slot = "data", vars = c("IdentI", paste0(genes_selected))) %>% 
  mutate(IdentI=factor(IdentI, levels = rev(cluster_order))) %>% 
  group_by(IdentI) %>% 
  summarise_all(mean) %>% 
  pivot_longer(cols = 2:ncol(.), names_to = "Gene") %>% 
  group_by(Gene) %>% 
  mutate(value=(value-min(value))/(max(value)-min(value))) %>% 
  left_join(., perc_expr) %>% 
  ggplot(aes(x=Gene, y=IdentI, size=100*Prop, fill=value))+
  geom_point(shape=21, stroke=0.1, color="grey45")+ 
  scale_size_continuous(range=c(0, 3), name="% pos. cells", limits=c(0, 100))+
  scale_fill_gradientn(name="Expression", colours = brewer.pal(5, "BuGn"), limits=c(0,1))+
  scale_y_discrete(limits=factor(rev(cluster_order)), labels=rev(unlist(labels_cl)))+
  scale_x_discrete(limits=genes_selected)+
  geom_hline(yintercept = c(1.5, 5.5, 9.5, 10.5, 13.5), linetype="solid", size=0.25, alpha=0.1)+
  ggtitle("RNA level")+
  coord_cartesian(clip = "off")+
  theme_bw()+
  mytheme_1+
  theme(axis.title = element_blank(),
        axis.text.x = element_text(angle = 45, hjust = 1, size=7),
        axis.text.y = element_blank(),
        axis.ticks.y = element_blank(),
        plot.margin = unit(c(0.25,0.35,0,2), "cm"))

lines <- c(1, 5, 9, 10, 13, 14)

for(i in 1:length(cluster_order)) {
  
  plot_genex <- plot_genex+
   annotation_custom(grob = rectGrob(gp = gpar(fill=colors_umap_cl[as.character(rev(cluster_order)[i])], lex=1, col="white")), 
                    ymin = seq(0.5, length(cluster_order)-0.5, 1)[i], 
                    ymax = seq(1.5, length(cluster_order)+0.5, 1)[i],
                    xmin = 0, xmax = -1.5)+
   annotation_custom(grob = textGrob(label = paste0("C", c(14:1)[i]), gp = gpar(cex=0.6, col=ifelse(i %in% c(6,7,11,14), "white", "black"))),
                    ymin = seq(0.5, length(cluster_order)-0.5, 1)[i], 
                    ymax = seq(1.5, length(cluster_order)+0.5, 1)[i],
                    xmin = 0, xmax = -1.5)
}

for(i in 1:length(lines)) {
  
  plot_genex <- plot_genex+
    annotation_custom(grob = textGrob(label = rev(labels_celltypes_expr)[[i]], rot = 0, hjust = 1, gp = gpar(cex=0.6)), 
                      ymin = c(0,lines)[i]+0.5,
                      ymax = c(lines)[i]+0.5,
                      xmin = -1.65, xmax = -1.65)+
    annotation_custom(grob = linesGrob(gp = gpar(col="white", lex=3)),
                      ymin = c(0,lines)[i]+0.5,
                      ymax = c(0,lines)[i]+0.5,
                      xmin = -0.01, xmax = -1.5)
}

plot_genex <- plot_genex+labs(tag = "B")+
 theme(plot.tag.position = c(-0.25,1))

Protein expression

Selected proteins

proteins_selected <- 
  c("CD4"="CD4", 
    "CD8a"="CD8a", 
    "CD45RA"="CD45RA", 
    "CD45RO"="CD45RO", 
    "CD95"="CD95", 
    "CD62L"="CD62L", 
    "CD127"="CD127", 
    "CD69"="CD69", 
    "CD38"="CD38", 
    "CD25"="CD25", 
    "ICOS"="CD278", 
    "CXCR5"="CD185", 
    "CD31"="CD31", 
    "KLRG1"="KLRG1", 
    "CD244"="CD244", 
    "PD1"="CD279", 
    "TIM3"="CD366"
    )

Plot

plot_protex <- 
  left_join(percentageADT, meanADT) %>% 
  filter(Epitope %in% proteins_selected) %>% 
  ggplot(aes(x=Epitope, y=IdentI, size=100*Prop, fill=Expression))+
  geom_point(shape=21, stroke=0.1, color="grey45")+ 
  geom_hline(yintercept = c(1.5, 5.5, 9.5, 10.5, 13.5), linetype="solid", size=0.25, alpha=0.1)+
  scale_size_continuous(range=c(0, 3), name="% pos. cells", limits=c(0, 100))+
  scale_fill_gradientn(name="Expression", colours = brewer.pal(5, "BuGn"), limits=c(0,1))+
  scale_y_discrete(limits=factor(rev(cluster_order)), labels=rev(unlist(labels_cl)))+
  scale_x_discrete(limits=proteins_selected, labels=names(proteins_selected))+
  ggtitle("Protein level")+
  coord_cartesian(clip = "off")+
  theme_bw()+
  mytheme_1+
  theme(axis.title = element_blank(),
        legend.position = "right",
        axis.text.x = element_text(angle = 45, hjust = 1, size=7),
        axis.text.y = element_blank(),
        axis.ticks.y = element_blank(),
        legend.text = element_text(size = 7, color="black"),
        legend.title = element_text(size = 7, color="black", vjust = 0.8),
        legend.key.height = unit(0.3, "cm"),
        legend.key.width = unit(0.3, "cm"),
        legend.box.spacing = unit(0.1, "cm"),
        plot.margin = unit(c(0.25,0,0,0.15), "cm"),
        plot.tag.position = c(-0.025,1))+
        labs(tag = "C")

Assemble plot

plot_genex+plot_protex+plot_layout(widths = c(1, 1.15))

#ggsave(filename = "Figure1_p2.pdf", width = 15, height = 7.8, units = "cm")

TF activity

Selected TFs

tfs_selected <- c("TCF7"="tfactivity_TCF7-E",  
                  "FOXP3"="tfactivity_FOXP3-E",
                  "ASCL2"="tfactivity_ASCL2-E", 
                  "KLF2"="tfactivity_KLF2-E")

Plot

df_tfs <- 
  FetchData(Combined_T, vars = c("Barcode_full", unname(tfs_selected))) %>% 
  left_join(df_comb %>% select(IdentI, Barcode_full, CellType), .) %>% 
  pivot_longer(cols =4:ncol(.)) %>% 
  mutate(name=gsub(name, pattern = "tfactivity_|-E", replacement = "")) %>% 
  mutate(name=factor(name, levels = names(tfs_selected))) %>% 
  group_by(name, IdentI) %>% 
  summarise(Mean=mean(value, na.rm=T)) %>% 
  group_by(name) %>% 
  mutate(Mean=2*((Mean-min(Mean))/(max(Mean)-min(Mean)))-1) 

plot_tfact <- 
  ggplot(df_tfs, aes(y=as.character(IdentI), x=name, fill=Mean))+
  geom_tile()+ 
  scale_fill_gradientn(name="TF activity", colours = colorRampPalette(colors = c("#762a83", "#f7f7f7", "#1b7837"))(100))+
  geom_vline(xintercept = seq(1.5, 4.5, 1), color="white", size=0.25)+
  geom_hline(yintercept = seq(1.5, 14.5, 1), color="white", size=0.25)+
  scale_y_discrete(limits=rev(factor(cluster_order)), expand = c(0,0))+
  scale_x_discrete(expand = c(0,0))+
  ggtitle("TF activity")+
  coord_fixed(clip = "off")+
  theme_bw()+
  mytheme_1+
  theme(axis.title = element_blank(),
        axis.text.x = element_text(angle = 45, hjust = 1, size=7),
        axis.text.y = element_blank(),
        axis.ticks.y = element_blank(),
        panel.border = element_rect(size=0.25),
        plot.background = element_rect(fill = NA, color=NA),
        legend.position = "right",
        legend.text = element_text(size = 7, color="black"),
        legend.key.height = unit(0.3, "cm"),
        legend.key.width = unit(0.3, "cm"),
        legend.box.spacing = unit(0.1, "cm"),
        plot.margin = unit(c(0.25,0,0,0.65), "cm"),
        plot.tag.position = c(-0.2,1))+
        labs(tag = "D")

lines <- c(1, 5, 9, 10, 13, 14)

for(i in 1:length(cluster_order)) {
  
  plot_tfact <- plot_tfact+
   annotation_custom(grob = rectGrob(gp = gpar(fill=colors_umap_cl[as.character(rev(cluster_order)[i])], lex=1, col="white")), 
                    ymin = seq(0.5, length(cluster_order)-0.5, 1)[i], 
                    ymax = seq(1.5, length(cluster_order)+0.5, 1)[i],
                    xmin = 0, xmax = -1.5)+
   annotation_custom(grob = textGrob(label = paste0("C", c(14:1)[i]), gp = gpar(cex=0.6, col=ifelse(i %in% c(6,7,11,14), "white", "black"))),
                    ymin = seq(0.5, length(cluster_order)-0.5, 1)[i], 
                    ymax = seq(1.5, length(cluster_order)+0.5, 1)[i],
                    xmin = 0, xmax = -1.5)
}

for(i in 1:length(lines)) {
  
  plot_tfact <- plot_tfact+
    annotation_custom(grob = linesGrob(gp = gpar(col="white", lex=3)),
                      ymin = c(0,lines)[i]+0.5,
                      ymax = c(0,lines)[i]+0.5,
                      xmin = -0.01, xmax = -1.5)
}

plot_tfact

#ggsave(plot_tfact, filename = "Figure1_p3.pdf", width = 5, height = 7.35, units = "cm")

Dendrogram

# Dendrogramm CITEseq
data <- data.frame(
  level1="_Tcells",
  level2=c("_'T'[Pr]",
           rep("_'T'[H]",3),  
           "_'T'[FH]", 
           rep("_'T'[REG]",4),  
           rep("_'T'[TOX]",4), 
           "_'T'[DN]"),
  level3=c("_'T'[Pr]", 
           "TH_'CD4'^'+'*' Naive'",
           "TH_'CM'[1]", 
           "TH_'CM'[2]", 
           "_'T'[FH]",  
           "TREG_'CM'[1]", 
           "TREG_'CM'[2]", 
           "TREG_'EM'[1]", 
           "TREG_'EM'[2]", 
           "TTOX_'CD8'^'+'*' Naive'",
           "TTOX_'EM'[1]",
           "TTOX_'EM'[2]",
           "TTOX_'EM'[3]",
           "_'T'[DN]")
)

dim <- 0.5

edges_level1_2 <- data %>% select(level1, level2) %>% unique %>% rename(from=level1, to=level2)
edges_level2_3 <- data %>% select(level2, level3) %>% unique %>% rename(from=level2, to=level3)
edge_list=rbind(edges_level1_2, edges_level2_3)

vert <- data.frame(
  name=unique(c(data$level1, data$level2, data$level3))) %>% 
  mutate(cluster=as.character(c(NA, 14, 'TH', 6, 'TREG', "TTOX", 19, 1, 2, 9, 8, 13, 15, 11, 12, 3, 16, 5))) %>% 
  mutate(label=strsplit(name, split = "_") %>% sapply(., "[[", 2)) %>% 
  mutate(alpha=c(0,1,1,1,1,1,dim,1,dim,dim,dim,dim,dim,dim,1,dim,dim,1))

mygraph_cite <- graph_from_data_frame( edge_list ,vertices = vert)

plot_dendrogramm <- ggraph(mygraph_cite, layout = 'tree', circular = FALSE)+ 
  geom_edge_diagonal(strength = 1.4, edge_width=0.25)+
  geom_node_label(aes(label=label, color=cluster), 
                  parse = T, nudge_y=-0.1, label.padding =  unit(units = "cm", 0.2),
                  size=2.75, label.size = 0, label.r = unit(units = "cm", 0))+
  scale_color_manual(values = colors_umap_cl)+
  theme_void()+
  theme(legend.position = "none")

plot_dendrogramm

#ggsave(plot_dendrogramm, filename = "Figure1_p4.pdf", device = "pdf", width = 17.5, height = 3.5, units = "cm")

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