# Clear the current R environment
rm(list=ls())

## Load required R packages
library(ComplexHeatmap)
## 载入需要的程序包:grid
## ========================================
## ComplexHeatmap version 2.22.0
## Bioconductor page: http://bioconductor.org/packages/ComplexHeatmap/
## Github page: https://github.com/jokergoo/ComplexHeatmap
## Documentation: http://jokergoo.github.io/ComplexHeatmap-reference
## 
## If you use it in published research, please cite either one:
## - Gu, Z. Complex Heatmap Visualization. iMeta 2022.
## - Gu, Z. Complex heatmaps reveal patterns and correlations in multidimensional 
##     genomic data. Bioinformatics 2016.
## 
## 
## The new InteractiveComplexHeatmap package can directly export static 
## complex heatmaps into an interactive Shiny app with zero effort. Have a try!
## 
## This message can be suppressed by:
##   suppressPackageStartupMessages(library(ComplexHeatmap))
## ========================================
library(shinipsum)
## Warning: 程序包'shinipsum'是用R版本4.4.3 来建造的
library(ggplot2)
## Warning: 程序包'ggplot2'是用R版本4.5.1 来建造的
library(ggstatsplot)
## Warning: 程序包'ggstatsplot'是用R版本4.4.3 来建造的
## You can cite this package as:
##      Patil, I. (2021). Visualizations with statistical details: The 'ggstatsplot' approach.
##      Journal of Open Source Software, 6(61), 3167, doi:10.21105/joss.03167
library(patchwork)
## Warning: 程序包'patchwork'是用R版本4.5.1 来建造的
library(reshape2)
library(stringr)
library(limma)
library(tidyverse)
## Warning: 程序包'forcats'是用R版本4.5.1 来建造的
## -- Attaching core tidyverse packages ------------------------ tidyverse 2.0.0 --
## v dplyr     1.1.4     v readr     2.1.5
## v forcats   1.0.0     v tibble    3.2.1
## v lubridate 1.9.4     v tidyr     1.3.1
## v purrr     1.0.4
## -- Conflicts ------------------------------------------ tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
## i Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
# Check and set timeout for downloading (if needed)
getOption('timeout')
## [1] 60
options(timeout=10000)

# Import expression data, skipping the first 3 rows (likely metadata or header info)
data <- readxl::read_excel("BLOOD_BLD-2023-023644-mmc3.xlsx", skip = 3)
dim(data)  # Check dimensions
## [1] 2067   11
data[1:6, 1:6]  # Preview first few rows and columns
## # A tibble: 6 x 6
##   gene_id       cluster gene_name sgLuc_DMSO_rep1 sgLuc_DMSO_rep2 sgLuc_VTP_rep1
##   <chr>         <chr>   <chr>               <dbl>           <dbl>          <dbl>
## 1 ENSG00000002~ cluste~ SNX11                9.41            9.28           9.78
## 2 ENSG00000005~ cluste~ HOXA11               8.62            8.65           9.68
## 3 ENSG00000005~ cluste~ MPO                 10.5            10.6           12.3 
## 4 ENSG00000008~ cluste~ MMP25                9.90            9.96          11.4 
## 5 ENSG00000011~ cluste~ TYROBP              11.2            11.1           12.0 
## 6 ENSG00000013~ cluste~ MAN2B2               9.82            9.96          10.5
# Define marker genes for each cluster
marker <- list(
  cluster1 = c("CTSA", "SMPD1"),
  cluster2 = c("CD14", "CD86", "FGR", "TLR8", "ITGAM"),
  cluster3 = c("MEIS1", "PBX3", "MEF2C"),
  cluster4 = c("MYC", "LRP5", "RUNX3")
)
marker
## $cluster1
## [1] "CTSA"  "SMPD1"
## 
## $cluster2
## [1] "CD14"  "CD86"  "FGR"   "TLR8"  "ITGAM"
## 
## $cluster3
## [1] "MEIS1" "PBX3"  "MEF2C"
## 
## $cluster4
## [1] "MYC"   "LRP5"  "RUNX3"
## Style settings for gene name annotations
tcol <- c("black", "black", "#34b3e6", "#f46951")  # Text color per cluster
bg <- c("#e8f8f8", "#fdefe9", "#e9f6fb", "#fde8e9")  # Background color per cluster

# Convert gene lists into styled data frames for textbox annotations
for(i in 1:length(marker)) {
  marker[[i]] <- data.frame(
    text = marker[[i]],
    fontsize = 12,
    col = tcol[i],
    fontface = "italic"
  )
}
marker
## $cluster1
##    text fontsize   col fontface
## 1  CTSA       12 black   italic
## 2 SMPD1       12 black   italic
## 
## $cluster2
##    text fontsize   col fontface
## 1  CD14       12 black   italic
## 2  CD86       12 black   italic
## 3   FGR       12 black   italic
## 4  TLR8       12 black   italic
## 5 ITGAM       12 black   italic
## 
## $cluster3
##    text fontsize     col fontface
## 1 MEIS1       12 #34b3e6   italic
## 2  PBX3       12 #34b3e6   italic
## 3 MEF2C       12 #34b3e6   italic
## 
## $cluster4
##    text fontsize     col fontface
## 1   MYC       12 #f46951   italic
## 2  LRP5       12 #f46951   italic
## 3 RUNX3       12 #f46951   italic
str(marker)
## List of 4
##  $ cluster1:'data.frame':    2 obs. of  4 variables:
##   ..$ text    : chr [1:2] "CTSA" "SMPD1"
##   ..$ fontsize: num [1:2] 12 12
##   ..$ col     : chr [1:2] "black" "black"
##   ..$ fontface: chr [1:2] "italic" "italic"
##  $ cluster2:'data.frame':    5 obs. of  4 variables:
##   ..$ text    : chr [1:5] "CD14" "CD86" "FGR" "TLR8" ...
##   ..$ fontsize: num [1:5] 12 12 12 12 12
##   ..$ col     : chr [1:5] "black" "black" "black" "black" ...
##   ..$ fontface: chr [1:5] "italic" "italic" "italic" "italic" ...
##  $ cluster3:'data.frame':    3 obs. of  4 variables:
##   ..$ text    : chr [1:3] "MEIS1" "PBX3" "MEF2C"
##   ..$ fontsize: num [1:3] 12 12 12
##   ..$ col     : chr [1:3] "#34b3e6" "#34b3e6" "#34b3e6"
##   ..$ fontface: chr [1:3] "italic" "italic" "italic"
##  $ cluster4:'data.frame':    3 obs. of  4 variables:
##   ..$ text    : chr [1:3] "MYC" "LRP5" "RUNX3"
##   ..$ fontsize: num [1:3] 12 12 12
##   ..$ col     : chr [1:3] "#f46951" "#f46951" "#f46951"
##   ..$ fontface: chr [1:3] "italic" "italic" "italic"
# Pathway or functional annotations for each cluster
annotation <- list(
  cluster1 = c("Lysosome"), 
  cluster2 = c("CD14 Positive Monocyte", "CD33 Positive Myeloid", "Regulation of Inflammatory Response", 
               "Hematopoietic cell lineage", "Increased Monocyte Cell number"), 
  cluster3 = c("KMT2A Fusion Target Genes", "MLL-AF6-Spreading Target Genes"), 
  cluster4 = c("Ribosome Biogenesis", "Myc Targets V2")
)

# Convert annotation list into styled data frames
for(i in 1:length(annotation)) {
  annotation[[i]] <- data.frame(
    text = annotation[[i]],
    fontsize = 11.3,
    col = "black"
  )
}
annotation
## $cluster1
##       text fontsize   col
## 1 Lysosome     11.3 black
## 
## $cluster2
##                                  text fontsize   col
## 1              CD14 Positive Monocyte     11.3 black
## 2               CD33 Positive Myeloid     11.3 black
## 3 Regulation of Inflammatory Response     11.3 black
## 4          Hematopoietic cell lineage     11.3 black
## 5      Increased Monocyte Cell number     11.3 black
## 
## $cluster3
##                             text fontsize   col
## 1      KMT2A Fusion Target Genes     11.3 black
## 2 MLL-AF6-Spreading Target Genes     11.3 black
## 
## $cluster4
##                  text fontsize   col
## 1 Ribosome Biogenesis     11.3 black
## 2      Myc Targets V2     11.3 black
# Adjusted p-values for each pathway annotation
adj_p_values <- list(
  cluster1 = c(1.862e-9), 
  cluster2 = c(6.094e-55, 9.956e-47, 2.308e-12, 3.595e-8, 5.908e-5), 
  cluster3 = c(4.557e-11, 1.715e-7), 
  cluster4 = c(1.030e-16, 2.745e-14)
)

# Format p-values as text annotation
for(i in 1:length(adj_p_values)) {
  adj_p_values[[i]] <- data.frame(
    text = as.character(adj_p_values[[i]]),
    fontsize = 11.3,
    col = "black"
  )
}
adj_p_values
## $cluster1
##        text fontsize   col
## 1 1.862e-09     11.3 black
## 
## $cluster2
##        text fontsize   col
## 1 6.094e-55     11.3 black
## 2 9.956e-47     11.3 black
## 3 2.308e-12     11.3 black
## 4 3.595e-08     11.3 black
## 5 5.908e-05     11.3 black
## 
## $cluster3
##        text fontsize   col
## 1 4.557e-11     11.3 black
## 2 1.715e-07     11.3 black
## 
## $cluster4
##        text fontsize   col
## 1  1.03e-16     11.3 black
## 2 2.745e-14     11.3 black
## Heatmap construction
# Extract numeric matrix and set gene symbols as row names
mat <- as.matrix(data[,-c(1:3)])
rownames(mat) <- data$gene_id
dim(mat)
## [1] 2067    8
head(mat)
##                 sgLuc_DMSO_rep1 sgLuc_DMSO_rep2 sgLuc_VTP_rep1 sgLuc_VTP_rep2
## ENSG00000002919        9.408104        9.282241       9.777550       9.773726
## ENSG00000005073        8.615269        8.647978       9.678552       9.699707
## ENSG00000005381       10.534899       10.625492      12.303269      12.287824
## ENSG00000008516        9.897188        9.964641      11.437336      11.438829
## ENSG00000011600       11.168022       11.145130      12.036846      11.966498
## ENSG00000013288        9.819726        9.957936      10.501483      10.472438
##                 sgPCGF1_DMSO_rep1 sgPCGF1_DMSO_rep2 sgPCGF1_VTP_rep1
## ENSG00000002919          9.521928          9.665968         9.644823
## ENSG00000005073          9.152883          9.107757         9.240887
## ENSG00000005381         10.199645         10.312349        12.854775
## ENSG00000008516         10.568840         10.616849        11.108043
## ENSG00000011600         11.384284         11.590741        11.650581
## ENSG00000013288         10.748916         10.663170        10.832866
##                 sgPCGF1_VTP_rep2
## ENSG00000002919         9.614058
## ENSG00000005073         9.254842
## ENSG00000005381        13.106643
## ENSG00000008516        11.034186
## ENSG00000011600        11.572871
## ENSG00000013288        10.974700
# Normalize gene expression (Z-score by row/gene)
mat <- t(scale(t(mat)))

# Clean column names (remove "_rep")
colnames(mat) <- str_split(colnames(mat), "_rep", simplify = TRUE)[,1]

# Row cluster group labels
split <- data$cluster
split
##    [1] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##    [7] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##   [13] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##   [19] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##   [25] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##   [31] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##   [37] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##   [43] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##   [49] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##   [55] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##   [61] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##   [67] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##   [73] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##   [79] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##   [85] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##   [91] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##   [97] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [103] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [109] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [115] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [121] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [127] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [133] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [139] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [145] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [151] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [157] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [163] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [169] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [175] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [181] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [187] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [193] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [199] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [205] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [211] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [217] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [223] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [229] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [235] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [241] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [247] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [253] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [259] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [265] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [271] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [277] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [283] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [289] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [295] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [301] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [307] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [313] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [319] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [325] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [331] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [337] "cluster1" "cluster1" "cluster1" "cluster1" "cluster1" "cluster1"
##  [343] "cluster1" "cluster1" "cluster1" "cluster2" "cluster2" "cluster2"
##  [349] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [355] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [361] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [367] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [373] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [379] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [385] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [391] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [397] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [403] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [409] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [415] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [421] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [427] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [433] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [439] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [445] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [451] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [457] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [463] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [469] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [475] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [481] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [487] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [493] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [499] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [505] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [511] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [517] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [523] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [529] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [535] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [541] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [547] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [553] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [559] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [565] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [571] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [577] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [583] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [589] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [595] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [601] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [607] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [613] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [619] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [625] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [631] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [637] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [643] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [649] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [655] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [661] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [667] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [673] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [679] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [685] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [691] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [697] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [703] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [709] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [715] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [721] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [727] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [733] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [739] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [745] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [751] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [757] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [763] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [769] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [775] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [781] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [787] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [793] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [799] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [805] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [811] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [817] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [823] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [829] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [835] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [841] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [847] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [853] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [859] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [865] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [871] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [877] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [883] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [889] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [895] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [901] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [907] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [913] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [919] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [925] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [931] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [937] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [943] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [949] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [955] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [961] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [967] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [973] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [979] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [985] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [991] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
##  [997] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
## [1003] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
## [1009] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
## [1015] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
## [1021] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
## [1027] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
## [1033] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
## [1039] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
## [1045] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
## [1051] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
## [1057] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
## [1063] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
## [1069] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
## [1075] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
## [1081] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
## [1087] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
## [1093] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
## [1099] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
## [1105] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
## [1111] "cluster2" "cluster2" "cluster2" "cluster2" "cluster2" "cluster2"
## [1117] "cluster2" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1123] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1129] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1135] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1141] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1147] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1153] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1159] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1165] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1171] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1177] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1183] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1189] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1195] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1201] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1207] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1213] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1219] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1225] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1231] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1237] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1243] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1249] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1255] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1261] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1267] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1273] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1279] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1285] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1291] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1297] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1303] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1309] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1315] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1321] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1327] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1333] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1339] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1345] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1351] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1357] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1363] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1369] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1375] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1381] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1387] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1393] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1399] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1405] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1411] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1417] "cluster3" "cluster3" "cluster3" "cluster3" "cluster3" "cluster3"
## [1423] "cluster3" "cluster3" "cluster3" "cluster3" "cluster4" "cluster4"
## [1429] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1435] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1441] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1447] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1453] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1459] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1465] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1471] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1477] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1483] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1489] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1495] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1501] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1507] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1513] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1519] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1525] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1531] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1537] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1543] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1549] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1555] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1561] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1567] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1573] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1579] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1585] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1591] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1597] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1603] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1609] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1615] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1621] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1627] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1633] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1639] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1645] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1651] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1657] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1663] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1669] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1675] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1681] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1687] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1693] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1699] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1705] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1711] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1717] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1723] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1729] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1735] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1741] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1747] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1753] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1759] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1765] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1771] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1777] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1783] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1789] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1795] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1801] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1807] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1813] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1819] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1825] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1831] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1837] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1843] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1849] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1855] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1861] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1867] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1873] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1879] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1885] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1891] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1897] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1903] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1909] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1915] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1921] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1927] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1933] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1939] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1945] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1951] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1957] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1963] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1969] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1975] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1981] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1987] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1993] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [1999] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [2005] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [2011] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [2017] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [2023] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [2029] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [2035] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [2041] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [2047] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [2053] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [2059] "cluster4" "cluster4" "cluster4" "cluster4" "cluster4" "cluster4"
## [2065] "cluster4" "cluster4" "cluster4"
# Create textbox annotation for genes (left panel)
ha <- rowAnnotation(
  textbox1 = anno_textbox(
    split, marker,
    add_new_line = TRUE,
    word_wrap = TRUE,
    line_space = unit(3, "mm"),
    background_gp = gpar(fill = bg, col = NA),
    by = "anno_block"
  )
)

# Create textbox annotation for functional/pathway descriptions
ha1 <- rowAnnotation(
  textbox2 = anno_textbox(
    split, annotation,
    add_new_line = TRUE,
    word_wrap = TRUE,
    line_space = unit(3, "mm"),
    background_gp = gpar(fill = bg, col = NA),
    by = "anno_block"
  )
)

# Create textbox annotation for adjusted p-values
ha2 <- rowAnnotation(
  textbox3 = anno_textbox(
    split, adj_p_values,
    add_new_line = TRUE,
    word_wrap = TRUE,
    line_space = unit(3, "mm"),
    background_gp = gpar(fill = bg, col = NA),
    by = "anno_block"
  )
)

# Start plotting to PDF
pdf(file = "Fig4.pdf", height = 7, width = 11)

# Create heatmap and combine with annotations
ht_list = Heatmap(
  mat, name = "mat",
  cluster_rows = FALSE,
  row_split = split,
  show_row_names = FALSE,
  cluster_columns = FALSE,
  row_title_rot = 0,
  row_title_gp = gpar(fontsize = 12),
  heatmap_legend_param = list(direction = "horizontal", nrow = 1),
  column_names_side = "top",
  right_annotation = ha
) + ha1 + ha2

# Draw heatmap with legend placed at the bottom
draw(ht_list, heatmap_legend_side = "bottom")

# Add titles to each annotation textbox
decorate_annotation("textbox1", {
  grid.text("Genes", y = unit(1, "npc") + unit(2, "mm"), just = "bottom")
})
decorate_annotation("textbox2", {
  grid.text("Annotation", y = unit(1, "npc") + unit(2, "mm"), just = c("right", "bottom"))
})
decorate_annotation("textbox3", {
  grid.text("Adj.Pvalue", y = unit(1, "npc") + unit(2, "mm"), just = "bottom")
})

# Return heatmap object (optional)
ht_list

# Close PDF output
dev.off()
## png 
##   2