Helping functions

In order to simplify the code, we define a heatmap function with some default parameters and some contants.

pheatmap_default <- function(
    ...,  # all parameters
    cluster_rows = FALSE,  # no clustering of rows
    cluster_cols = FALSE,  # no clustering of columns 
    breaks
) {
  if (!missing(breaks)) {
    if (length(breaks) == 1) breaks = c(-1, 1) * breaks
    if (length(breaks) == 2) breaks = seq(breaks[1], breaks[2], length.out = 101)
    pheatmap(
      ..., cluster_rows = cluster_rows, cluster_cols = cluster_cols, breaks = breaks
    )
  } else {
    pheatmap(
      ..., cluster_rows = cluster_rows, cluster_cols = cluster_cols
    )
  }
}
cs_top = "#D73020"
cs_mid = "#FEFEBF"
cs_bot = "#4575B4"

Reading MFI

We read the prepared matrix of MFIs as well as the sample information.

# ==== READING ALL PREPARED DATA FROM R ========================================

load("output/mfis_Assignment.RData")

Transforming

We will start with the display of the raw MFIs although it is not ready for an interpretation. As the MFIs were extracted without any transformation, we apply the asinh function with a cofactor of 5 for mass cytometry.

mfis = asinh(mfis/5)
pheatmap_default(mfis)

The color scale covers automatically the range of transformed intensities across all the matrix. There is a high value in CD38 marker that reduces the available colors in the other markers.

Normalizing to the maximum per marker

To adjust the color scale per marker, each marker is scaled independently.

mfis_max = apply(mfis, 2, max)
mfis_to_max = sweep(mfis, 2, mfis_max, "/")

pheatmap_default(mfis_to_max)

This leads to a better and finer reading. Care must be taken with lowly expressed markers.

Normalizing to the minimum and maximum per marker

The adjustment could take into account the minimum and the maximum of each marker, each marker being scaled independently.

mfis_min = apply(mfis, 2, min)
mfis_to_min_max = sweep(mfis, 2, mfis_min, "-")
mfis_max = apply(mfis_to_min_max, 2, max)
mfis_to_min_max = sweep(mfis_to_min_max, 2, mfis_max, "/")

pheatmap_default(mfis_to_min_max)

This leads to a better and finer reading. Care must be taken with lowly expressed markers.

Clustering

The clustering of the markers and the clusters eases the reading and interpretation and fastens the cluster annotation.

pheatmap(mfis_to_min_max, breaks = seq(0, 1, length.out = 101))

# figure for the article
pheatmap(mfis_to_min_max, breaks = seq(0, 1, length.out = 101), fontsize = 11)

Script session

Session info
## R version 4.4.2 (2024-10-31 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 22631)
## 
## Matrix products: default
## 
## 
## locale:
## [1] LC_COLLATE=French_France.utf8  LC_CTYPE=French_France.utf8   
## [3] LC_MONETARY=French_France.utf8 LC_NUMERIC=C                  
## [5] LC_TIME=French_France.utf8    
## 
## time zone: Europe/Paris
## tzcode source: internal
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] readxl_1.4.3    pheatmap_1.0.12
## 
## loaded via a namespace (and not attached):
##  [1] digest_0.6.37      RColorBrewer_1.1-3 R6_2.5.1           fastmap_1.2.0     
##  [5] cellranger_1.1.0   xfun_0.50          gtable_0.3.6       glue_1.8.0        
##  [9] cachem_1.1.0       knitr_1.49         htmltools_0.5.8.1  rmarkdown_2.29    
## [13] lifecycle_1.0.4    cli_3.6.3          scales_1.3.0       grid_4.4.2        
## [17] sass_0.4.9         jquerylib_0.1.4    compiler_4.4.2     rstudioapi_0.17.1 
## [21] tools_4.4.2        munsell_0.5.1      evaluate_1.0.3     bslib_0.8.0       
## [25] colorspace_2.1-1   yaml_2.3.10        rlang_1.1.4        jsonlite_1.8.9