0

Following on from this example a few years ago I would like to colour code the segment labels in a chordDiagram using the circlize package in R.

Documentation in ?circos.text tells me that I should use the set this using the argument col in the graphical par parameters. However, par(col) does not accept a vector of colours.

Can someone please advice how to do this? Many thanks.

Example code here using circlize package in R.

library(circlize)
set.seed(999)

## generate example data
mat <- matrix(sample(18, 18), 3, 3)
rownames(mat) <- colnames(mat) <- paste0("A", 1:3)
df = data.frame(from = rep(rownames(mat), times = ncol(mat)),
                to = rep(colnames(mat), each = nrow(mat)),
                value = as.vector(mat),
                stringsAsFactors = FALSE)

## set colours for segments
grid.col <- setNames(rainbow(nrow(mat)), rownames(mat))

# now, plot the image with rotated labels
chordDiagram(df, annotationTrack = "grid", 
             preAllocateTracks = 1, 
             grid.col = grid.col,
             directional = 1, 
             direction.type = c("diffHeight", "arrows"), 
             link.arr.type = "big.arrow")

circos.trackPlotRegion(track.index = 1, panel.fun = function(x, y) {
  xlim = get.cell.meta.data("xlim")
  ylim = get.cell.meta.data("ylim")
  sector.name = get.cell.meta.data("sector.index")
  circos.text(mean(xlim), 
              ylim[1] + .1, 
              sector.name, 
              facing = "clockwise", 
              niceFacing = TRUE, 
              adj = c(-0.5, 0.5))
  circos.axis(h = "top", 
              labels.cex = 0.5, 
              major.tick.percentage = 0.2, 
              sector.index = sector.name, 
              track.index = 2)
}, bg.border = NA)

This produces this nice plot

enter image description here

How can I change the labels A1, A2 and A3 to the same colour as their segments? par(col = grid.col) does not work as it only expects one colour in the vector. Thanks very much.

> sessionInfo()
R version 4.0.0 (2020-04-24)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS High Sierra 10.13.6

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRlapack.dylib

locale:
[1] en_GB.UTF-8/en_GB.UTF-8/en_GB.UTF-8/C/en_GB.UTF-8/en_GB.UTF-8

attached base packages:
[1] stats4    parallel  stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] ggplot2_3.3.1        reshape2_1.4.4       pRolocdata_1.26.0    pRoloc_1.29.0       
 [5] BiocParallel_1.22.0  MLInterfaces_1.68.0  cluster_2.1.0        annotate_1.66.0     
 [9] XML_3.99-0.3         AnnotationDbi_1.50.0 IRanges_2.22.2       MSnbase_2.14.2      
[13] ProtGenerics_1.20.0  S4Vectors_0.26.1     mzR_2.22.0           Rcpp_1.0.4.6        
[17] Biobase_2.48.0       BiocGenerics_0.34.0  dplyr_1.0.0          circlize_0.4.9      
[21] migest_1.8.1 
lmsimp
  • 882
  • 7
  • 22

2 Answers2

1

The circos.trackPlotRegion function loops over its argument x making a call to panel.function function each time. The effect is to use the first value of col for each call (col[1]) instead of respecting the vector of values in the argument col.

One solution may be to call to circos.trackPlotRegion for each sector as shown below:

# replace code after the call to `chordDiagram` with this

for (i in seq_len(nrow(mat))) { # use for loop to label each sector
  myFactor <- rownames(mat)[i] # assuming this defines the sectors
  myCol <- grid.col[i] # defined in the question
  circos.trackPlotRegion(track.index = 1, factor = myFactor,
    panel.fun = function(x, y) {
      xlim = get.cell.meta.data("xlim")
      ylim = get.cell.meta.data("ylim")
      sector.name = get.cell.meta.data("sector.index")
      circos.text(mean(xlim), 
        ylim[1] + .1, 
        sector.name,
        col = myCol,
        facing = "clockwise",
        niceFacing = TRUE, 
        adj = c(-0.5, 0.5))
      circos.axis(h = "top", 
        labels.cex = 0.5,
        major.tick.percentage = 0.2, 
        sector.index = sector.name, 
        track.index = 2)
      },
    bg.border = NA)
}
David O
  • 803
  • 4
  • 10
1

Alternatively, you can provide the colors as grid.col[sector.name]:

library(circlize)
set.seed(999)

## generate example data
mat <- matrix(sample(18, 18), 3, 3)
rownames(mat) <- colnames(mat) <- paste0("A", 1:3)
df = data.frame(from = rep(rownames(mat), times = ncol(mat)),
                to = rep(colnames(mat), each = nrow(mat)),
                value = as.vector(mat),
                stringsAsFactors = FALSE)

## set colours for segments
grid.col <- setNames(rainbow(nrow(mat)), rownames(mat))

# now, plot the image with rotated labels
chordDiagram(df, annotationTrack = "grid", 
             preAllocateTracks = 1, 
             grid.col = grid.col,
             directional = 1, 
             direction.type = c("diffHeight", "arrows"), 
             link.arr.type = "big.arrow")

circos.trackPlotRegion(track.index = 1, panel.fun = function(x, y) {
    xlim = get.cell.meta.data("xlim")
    ylim = get.cell.meta.data("ylim")
    sector.name = get.cell.meta.data("sector.index")
    circos.text(mean(xlim), 
                ylim[1] + .1, 
                sector.name, 
                facing = "clockwise", 
                niceFacing = TRUE, 
                adj = c(-0.5, 0.5),
                col=grid.col[sector.name])
    circos.axis(h = "top", 
                labels.cex = 0.5, 
                major.tick.percentage = 0.2, 
                sector.index = sector.name, 
                track.index = 2)
}, bg.border = NA)

Created on 2020-06-27 by the reprex package (v0.3.0)

user12728748
  • 8,106
  • 2
  • 9
  • 14