0

I am trying to create a Chord diagram in R using the circlize package by following the examples from https://jokergoo.github.io/circlize_book/book/legends.html. This works fine, but I run into errors trying to insert some figure legends using the gridbase and Complexheatmap R packages.

I am supposed to set the "omi" parameter using par(omi = gridOMI(), new = TRUE). Unfortunately, par does not seem to recognize the vector created by gridOMI() as correct input and I don't know why.

The code I have is this:

library(circlize)
library(ComplexHeatmap)
library(tidyverse)
library(gridBase)
library(grid)

df <- structure(list(term_name = c("cats", "dogs", "goldfish", "hamster", 
                             "quinea pig", "snake", "cats", "quinea pig", "capybara", "quinea pig", 
                             "snake", "cats", "cats", "cats", "dogs", "goldfish", "dogs", 
                             "goldfish", "dogs", "goldfish", "dogs", "goldfish", "dogs", "goldfish", 
                             "capybara", "dogs", "goldfish", "dogs", "goldfish", "goldfish"
), Gene = c("A1", "A2", "A2", "A2", "A2", "A3", "A3", "A4", "B1", 
            "B2", "B3", "B3", "B4", "B5", "B6", "B6", "B7", "B7", "B8", "B8", 
            "C1", "C1", "C2", "C2", "C3", "C4", "C4", "C5", "C5", "C6"), 
adjusted_p_value = c(0.0401123837727216, 0.00599293759030441, 
                     0.008037018541932, 0.0238949037996737, 0.0455988630423016, 
                     0.0362906272864953, 0.0401123837727216, 0.0455988630423016, 
                     0.0175800574990072, 0.0455988630423016, 0.0362906272864953, 
                     0.0401123837727216, 0.0401123837727216, 0.0401123837727216, 
                     0.00599293759030441, 0.008037018541932, 0.00599293759030441, 
                     0.008037018541932, 0.00599293759030441, 0.008037018541932, 
                     0.00599293759030441, 0.008037018541932, 0.00599293759030441, 
                     0.008037018541932, 0.0175800574990072, 0.00599293759030441, 
                     0.008037018541932, 0.00599293759030441, 0.008037018541932, 
                     0.008037018541932), FoldChange = c(9.65818273715244, 8.77862464376709, 
                                                        8.77862464376709, 8.77862464376709, 8.77862464376709, 8.56731315195869, 
                                                        8.56731315195869, 8.43444706073958, 8.12991568737931, 8.12449961176595, 
                                                        8.08270580330019, 8.08270580330019, 8.02040115004825, 8.00996652274416, 
                                                        7.64451918356123, 7.64451918356123, 7.2756458952698, 7.2756458952698, 
                                                        6.14815597897133, 6.14815597897133, 5.8393823870724, 5.8393823870724, 
                                                        5.70624023824579, 5.70624023824579, 5.31939602787647, 5.14071417928765, 
                                                        5.14071417928765, 5.00924279397654, 5.00924279397654, 4.87034859437948
                     )), row.names = c(NA, -30L), class = c("tbl_df", "tbl", "data.frame"
                     ))

### Chord diagram code

# create color ranges for visualization
col_fun_pval = colorRamp2(c(min(df$adjusted_p_value), mean(df$adjusted_p_value), max(df$adjusted_p_value)), c("magenta", "green", "blue"))
#col_fun_FC = colorRamp2(range(df$FoldChange), c("#FFE6E6", "#FF0000"))
col_fun_FC = colorRamp2(range(df$FoldChange), c("#b38f00", "#fffae6"))


# map grid color values to Fold change values. GO grid color set to adjusted P-val.
gene_names <- unique(df$Gene)
Foldchange <- df$FoldChange[!duplicated(df$Gene)]
names(Foldchange) <- gene_names

GO_names <- unique(df$term_name)
GO_col <- df$adjusted_p_value[!duplicated(df$term_name)]
names(GO_col) <- GO_names

grid.col = c(col_fun_pval(GO_col), col_fun_FC(Foldchange))

#define Chord diagram plot function

Chord_plot <- function() {
  circos.par(gap.after = c(rep(6, length(unique(df[[1]]))-1), 10, 
                           rep(1, length(unique(df[[2]]))-1), 10),
             clock.wise = FALSE, start.degree = 180)
  
  chordDiagram(df[, 1:2], 
               col = col_fun_pval(df[, 3]), grid.col = grid.col, annotationTrack = "grid",
               directional = 1, link.border = NA, preAllocateTracks = list(track.height = max(strwidth(gene_names))))
  
  # we go back to the first track and customize sector labels
  circos.track(track.index = 1, panel.fun = function(x, y) {
    
    if (CELL_META$sector.index %in% gene_names) {
      circos.text(CELL_META$xcenter, CELL_META$ylim[1], CELL_META$sector.index, 
                  facing = "clockwise", niceFacing = TRUE, adj = c(0, 0.5), cex = 0.8)
    }
  }, bg.border = NA) # here set bg.border to NA is important
  
  circos.clear()
}

# create continuous legends
dig_num <- 2

lgd_FC = Legend(at = c(round(min(Foldchange), digits = dig_num),
                       round(min(Foldchange) + (1/4*(max(Foldchange - min(Foldchange)))), digits = dig_num),
                       round(min(Foldchange) + (2/4*(max(Foldchange - min(Foldchange)))), digits = dig_num),
                       round(min(Foldchange) + (3/4*(max(Foldchange - min(Foldchange)))), digits = dig_num),
                       round(min(Foldchange) + (4/4*(max(Foldchange - min(Foldchange)))), digits = dig_num)), 
                col_fun = col_fun_FC, 
                title_position = "topleft", title = "Fold Change")

lgd_pval = Legend(at = c(round(min(GO_col), digits = dig_num),
                         round(min(GO_col) + (1/4*(max(GO_col - min(GO_col)))), digits = dig_num),
                         round(min(GO_col) + (2/4*(max(GO_col - min(GO_col)))), digits = dig_num),
                         round(min(GO_col) + (3/4*(max(GO_col - min(GO_col)))), digits = dig_num),
                         round(min(GO_col) + (4/4*(max(GO_col - min(GO_col)))), digits = dig_num)),
                  col_fun = col_fun_pval,  
                  title_position = "topleft", title = "GO p-value")
# stack legends
lgd_list_vertical = packLegend(lgd_FC, lgd_pval)


### use gridbase to plot legends and chorddiagram

plot.new()
circle_size = unit(1, "snpc") # snpc unit gives you a square region
pushViewport(viewport(x = 0, y = 0.5, width = circle_size, height = circle_size,
                      just = c("left", "center")))

par(omi = gridOMI(), new = TRUE)

Chord_plot()

upViewport()

draw(lgd_list_vertical, x = circle_size, just = "left")

Trying to run the above code gives the following error

Error in par(omi = gridOMI(), new = TRUE) : 
  invalid value specified for graphical parameter "omi"

I don't know if it is a problem with my R version, package versions, package conflicts or something different. By googling I couldn't find anyone with the same problem.

Just in case it is important, here are the details from sessioninfo()

R version 4.2.0 (2022-04-22 ucrt)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 22000)

Matrix products: default

locale:
[1] LC_COLLATE=Dutch_Netherlands.utf8  LC_CTYPE=Dutch_Netherlands.utf8    LC_MONETARY=Dutch_Netherlands.utf8 LC_NUMERIC=C                      
[5] LC_TIME=Dutch_Netherlands.utf8    

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

other attached packages:
 [1] gridBase_0.4-7        forcats_0.5.2         stringr_1.4.1         dplyr_1.0.10          purrr_0.3.4           readr_2.1.2           tidyr_1.2.1          
 [8] tibble_3.1.8          ggplot2_3.3.6         tidyverse_1.3.2       ComplexHeatmap_2.12.1 circlize_0.4.15      

loaded via a namespace (and not attached):
 [1] httr_1.4.4          bit64_4.0.5         vroom_1.5.7         jsonlite_1.8.0      foreach_1.5.2       modelr_0.1.9        assertthat_0.2.1    stats4_4.2.0       
 [9] googlesheets4_1.0.1 cellranger_1.1.0    yaml_2.3.5          pillar_1.8.1        backports_1.4.1     glue_1.6.2          digest_0.6.29       RColorBrewer_1.1-3 
[17] rvest_1.0.3         colorspace_2.0-3    htmltools_0.5.3     pkgconfig_2.0.3     GetoptLong_1.0.5    broom_1.0.1         haven_2.5.1         scales_1.2.1       
[25] tzdb_0.3.0          googledrive_2.0.0   generics_0.1.3      IRanges_2.30.0      ellipsis_0.3.2      withr_2.5.0         BiocGenerics_0.42.0 cli_3.3.0          
[33] magrittr_2.0.3      crayon_1.5.1        readxl_1.4.1        evaluate_0.16       fs_1.5.2            fansi_1.0.3         doParallel_1.0.17   xml2_1.3.3         
[41] tools_4.2.0         hms_1.1.2           GlobalOptions_0.1.2 gargle_1.2.1        lifecycle_1.0.2     matrixStats_0.62.0  S4Vectors_0.34.0    munsell_0.5.0      
[49] reprex_2.0.2        cluster_2.1.3       compiler_4.2.0      rlang_1.0.6         iterators_1.0.14    rstudioapi_0.14     rjson_0.2.21        rmarkdown_2.16     
[57] gtable_0.3.1        codetools_0.2-18    DBI_1.1.3           R6_2.5.1            lubridate_1.8.0     knitr_1.40          fastmap_1.1.0       bit_4.0.4          
[65] utf8_1.2.2          clue_0.3-61         shape_1.4.6         stringi_1.7.8       parallel_4.2.0      vctrs_0.4.1         png_0.1-7           xfun_0.33          
[73] dbplyr_2.2.1        tidyselect_1.1.2 

Any help would be really appreciated, as I am kind of stuck on this error.

EDIT: I found out I do not get this error in another system. If I do sessioninfo() there, I get the following outout

R version 4.1.1 (2021-08-10)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: CentOS Linux 7 (Core)

Matrix products: default
BLAS:   /sw/apps/R/4.1.1/rackham/lib64/R/lib/libRblas.so
LAPACK: /sw/apps/R/4.1.1/rackham/lib64/R/lib/libRlapack.so

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=en_US.UTF-8       
 [4] LC_COLLATE=en_US.UTF-8     LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                  LC_ADDRESS=C              
[10] 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] gridBase_0.4-7       forcats_0.5.1        stringr_1.4.0        dplyr_1.0.7         
 [5] purrr_0.3.4          readr_2.0.2          tidyr_1.1.4          tibble_3.1.5        
 [9] ggplot2_3.3.5        tidyverse_1.3.1      circlize_0.4.13      ComplexHeatmap_2.8.0

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.7          lubridate_1.8.0     png_0.1-7           assertthat_0.2.1   
 [5] digest_0.6.28       foreach_1.5.1       utf8_1.2.2          R6_2.5.1           
 [9] cellranger_1.1.0    backports_1.3.0     reprex_2.0.1        stats4_4.1.1       
[13] httr_1.4.2          pillar_1.6.4        GlobalOptions_0.1.2 rlang_0.4.12       
[17] readxl_1.3.1        rstudioapi_0.13     S4Vectors_0.30.2    GetoptLong_1.0.5   
[21] munsell_0.5.0       broom_0.7.10        compiler_4.1.1      modelr_0.1.8       
[25] pkgconfig_2.0.3     BiocGenerics_0.38.0 shape_1.4.6         tidyselect_1.1.1   
[29] IRanges_2.26.0      codetools_0.2-18    matrixStats_0.61.0  fansi_0.5.0        
[33] crayon_1.4.2        tzdb_0.1.2          dbplyr_2.1.1        withr_2.4.2        
[37] jsonlite_1.7.2      gtable_0.3.0        lifecycle_1.0.1     DBI_1.1.1          
[41] magrittr_2.0.1      scales_1.1.1        cli_3.1.0           stringi_1.7.5      
[45] fs_1.5.0            doParallel_1.0.16   xml2_1.3.2          ellipsis_0.3.2     
[49] generics_0.1.1      vctrs_0.3.8         rjson_0.2.20        RColorBrewer_1.1-2 
[53] iterators_1.0.13    tools_4.1.1         Cairo_1.5-12.2      glue_1.5.0         
[57] hms_1.1.1           parallel_4.1.1      clue_0.3-60         colorspace_2.0-2   
[61] cluster_2.1.2       rvest_1.0.2         haven_2.4.3

I hope this helps. The main differences I notice is the R version, which is older on this system, and the locale.

  • Could you please share some reproducible data using `dput`? – Quinten Sep 26 '22 at 15:16
  • Sorry about that. I have added the full code with example data that should run with the code. I have edited my post and included it – Jari van Diermen Sep 26 '22 at 17:59
  • I cannot replicate this myself, but some ideas to help with debugging: what is the value from `gridOMI()` after the error? you mentioned elsewhere that the code runs on a different system - have you compared sessionInfo() on that system? The output is very sensitive to the size of the graphics device - are you running this in R itself, with a standard R graphics device, or via an IDE, e.g., R Studio? – Paul Murrell Oct 03 '22 at 20:00
  • Hey Paul, When I use gridOMI() on my computer, where I get the error, the output is: `[1] 0.0000 0.0000 -0.6977 2.2558`. On the system where I do not have the error, I get: `[1] 0 0 0 0`. Furthermore, I am running R via an IDE (Rstudio), on both systems. I added the sessioninfo() output of the other system, where no error occurs, to my original question. – Jari van Diermen Oct 03 '22 at 22:14
  • The -0.6977 is the problem. Not sure how you are getting that. Does your code work if you open a standard R graphics device first, e.g., by typing `dev.new()` – Paul Murrell Oct 04 '22 at 02:48
  • It does indeed kinda work. I do not get any errors with gridOMI() in the standard R graphics device window. However, when I am plotting the diagram, even after pushing the specified viewport, it doesn't limit the plotting region to the specified viewport. Interestingly, when I am using agg_png(), from the ragg library, to make and save the plot, I do get the correct png file, with the chorddiagram in the specified viewport and the legends visible. – Jari van Diermen Oct 04 '22 at 09:26
  • I have found a solution to the problem. By using ctrl + shift + (+-), you can zoom in/out the Rstudio window. Apparantly, gridOMI() gives these errors in the Rstudio graphical device, when Rstudio is zoomed out too much. – Jari van Diermen Oct 04 '22 at 09:36

1 Answers1

0

I found one solution. gridOMI() is apparantly sensitive to Rstudio's zoom function, which resizes the text and user-interface elements. For me, gridOMI() gave an invalid value, because I my user-interface elements were too small.

You can resize Rstudio's text and user-interface elements by clicking on zoom in or zoom out in the View menu.