rgraphicschord-diagramcirclize

R: circlize chord diagram with images as labels?


Is it possible to place images where the labels of a circlize chordDiagram would be?

For example, I have manually placed SVG outlines of the continents against the labels. I was wondering if there is a programmatic way to achieve this.

enter image description here

Here is a starter example to which I hope to be able to add image labels. Note that there is an example on the circlize site that appears to do what I want:

enter image description here

but I cannot combine that with this example:

mat = matrix(sample(100, 25), 5)
rownames(mat) = letters[1:5]
colnames(mat) = letters[1:5]

library(circlize)
chordDiagram(mat, directional = TRUE, transparency = 0.5)

Solution

  • In your example, you need to create one empty track at the most outside of the circle and later go back to this empty track to add raster images.

    In following example, preAllocateTracks argument is used to define how many empty tracks should be put. For more explanation of this argument, please refer to: http://zuguang.de/circlize_book/book/advanced-usage-of-chorddiagram.html#organization-of-tracks

    mat = matrix(sample(100, 25), 5)
    rownames(mat) = letters[1:5]
    colnames(mat) = letters[1:5]
    
    library(circlize)
    
    library(png)
    tmp = tempfile()
    download.file("https://www.google.de/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png", tmp)
    image = as.raster(readPNG(tmp))
    ratio = ncol(image)/nrow(image)
    
    chordDiagram(mat, directional = TRUE, transparency = 0.5,
        preAllocateTracks = 1)
    
    circos.track(track.index = 1, panel.fun = function(x, y) {
        xcenter = get.cell.meta.data("xcenter")
        ycenter = get.cell.meta.data("ycenter")
    
        pos = circlize:::polar2Cartesian(circlize(xcenter, ycenter))
    
        rasterImage(image, 
            xleft = pos[1, 1] - 0.05*ratio,
            ybottom = pos[1, 2] - 0.05,
            xright = pos[1, 1] + 0.05*ratio,
            ytop = pos[1, 2]+ 0.05)
    }, bg.border = NA)
    

    enter image description here

    It is also possible but not easy to rotate the images to let them face the center of the circle, because rasterImage() has a angle argument which allows rotating the image but the rotation is relative to the left bottom corner of the image while not the center of the image.

    EDIT: I have added a new function circos.raster() in the package (version >= 0.4.1) which makes adding raster images easier.