jolars / eulerr

Area-Proportional Euler and Venn Diagrams with Ellipses
https://jolars.github.io/eulerr/
GNU General Public License v3.0
129 stars 18 forks source link

Unable to plot to PNG #79

Closed TDCasasent closed 3 years ago

TDCasasent commented 3 years ago

I am unable to plot an Euler diagram to PNG (or PDF or JPEG or TIFF). Other plot functions work fine, such as using one of the example calls to the basic plot. Plot for Euler Diagrams will plot the diagram to the RStudio preview. But for files, the resulting PNG is plain black -- nothing was written to it.

Code to reproduce (taken from example). Set thePngFile to a value path.

` CairoPNG(file = thePngFile)

on.exit(dev.off())

three_inside_fourth <- euler(c("A" = 30, "A&B" = 3, "A&C" = 3, "A&D" = 3, "A&B&C" = 2, "A&B&D" = 2, "A&C&D" = 2, "A&B&C&D" = 1))

plot(three_inside_fourth)`

jolars commented 3 years ago

Hm, really? It works fine for me.

library(eulerr)
library(Cairo)

CairoPNG(file = "tmp.png")
three_inside_fourth <- euler(c("A" = 30,
                               "A&B" = 3, "A&C" = 3, "A&D" = 3,
                               "A&B&C" = 2, "A&B&D" = 2, "A&C&D" = 2,
                               "A&B&C&D" = 1))
plot(three_inside_fourth)

dev.off()
#> png 
#>   2

tmp

TDCasasent commented 3 years ago

Am I getting some sort of package interference, similar to #78 ? I'm not getting the error message seen there. But, if I make a function inside my package like so:

` closeTwice <- function() { logDebug("off1") dev.off() logDebug("off2") dev.off() logDebug("off2") }

writeManovaPNG2 <- function(thePngFile) { options(warn=0) try( closeTwice() ) CairoPNG(file = thePngFile) on.exit(dev.off(), add = TRUE) three_inside_fourth <- euler(c("A" = 30, "A&B" = 3, "A&C" = 3, "A&D" = 3, "A&B&C" = 2, "A&B&D" = 2, "A&C&D" = 2, "A&B&C&D" = 1)) plot(three_inside_fourth) logDebug("plotted") } `

And from an R sesssion from the command line (not in RStudion), call that function with a good path, as seen below, I don't get an error like #78 (beyond the warning about unable to close base device, which is expected). But I do get a pop-up PNG plotting what I expect. (MBatch is the name of my package.) But the PNG is empty.

`> library(MBatch) All sorting in this package requires using a Sys.setlocale("LC_COLLATE","C"). MBatch Version: BEA_VERSION_TIMESTAMP

writeManovaPNG2("/home/foo/man.png") 2020 12 18 15:46:11.552 DEBUG off1 Error in dev.off() : cannot shut down device 1 (the null device) 2020 12 18 15:46:11.655 DEBUG plotted

`

R session info is:

sessionInfo() R version 4.0.3 (2020-10-10) Platform: x86_64-redhat-linux-gnu (64-bit) Running under: Red Hat Enterprise Linux 8.3 (Ootpa)

Matrix products: default BLAS/LAPACK: /usr/lib64/libopenblas-r0.3.3.so

locale: [1] LC_CTYPE=C LC_NUMERIC=C LC_TIME=C
[4] LC_COLLATE=en_US.UTF-8 LC_MONETARY=C LC_MESSAGES=C
[7] LC_PAPER=C LC_NAME=en_US.UTF-8 LC_ADDRESS=en_US.UTF-8
[10] LC_TELEPHONE=en_US.UTF-8 LC_MEASUREMENT=C LC_IDENTIFICATION=en_US.UTF-8

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

other attached packages: [1] MBatch_1.7.2 eulerr_6.1.0 Cairo_1.5-12.2

loaded via a namespace (and not attached): [1] mclust_5.4.7 Rcpp_1.0.5 lattice_0.20-41 lubridate_1.7.9.2
[5] gtools_3.8.2 digest_0.6.27 grid_4.0.3 BiasedUrn_1.07
[9] oompaBase_3.2.9 Matrix_1.2-18 generics_0.1.0 squash_1.0.9
[13] ClassDiscovery_3.3.13 splines_4.0.3 tools_4.0.3 epiR_2.0.17
[17] pander_0.6.3 polyclip_1.10-0 polylabelr_0.2.0 parallel_4.0.3
[21] survival_3.2-7 compiler_4.0.3 oompaData_3.1.1 cluster_2.1.0
[25] rJava_0.9-13

I can also reproduce it outside my package with the same results, from a fresh R --vanilla session: ` > library(Cairo)

library(eulerr) writeManovaPNG2 <- function(thePngFile) { CairoPNG(file = thePngFile) on.exit(dev.off(), add = TRUE) three_inside_fourth <- euler(c("A" = 30, "A&B" = 3, "A&C" = 3, "A&D" = 3, "A&B&C" = 2, "A&B&D" = 2, "A&C&D" = 2, "A&B&C&D" = 1)) plot(three_inside_fourth) } writeManovaPNG2("/home/foo/man.png") `

TDCasasent commented 3 years ago

Session info for the vanilla command line session.

sessionInfo() R version 4.0.3 (2020-10-10) Platform: x86_64-redhat-linux-gnu (64-bit) Running under: Red Hat Enterprise Linux 8.3 (Ootpa)

Matrix products: default BLAS/LAPACK: /usr/lib64/libopenblas-r0.3.3.so

locale: [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
[3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
[5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
[7] LC_PAPER=en_US.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C

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

other attached packages: [1] eulerr_6.1.0 Cairo_1.5-12.2

loaded via a namespace (and not attached): [1] compiler_4.0.3 Rcpp_1.0.5 grid_4.0.3 polyclip_1.10-0 [5] polylabelr_0.2.0

jolars commented 3 years ago

Unless you're loading gplots, you shouldn't be having any interference.

I think the problem is that you're using on.exit() here. Why do you need that? Have you tried running the code I supplied in the last message?

TDCasasent commented 3 years ago

No gplots -- so that's good. Can you try my code? Your code pasted in to the R command line straight works. (tmp1.png is created with proper image.) The same code, wrapped in a function does not. (tmp2.png is empty -- an all black image.) Is there some sort of setup that I've missed to make it work within a function?

library(Cairo) library(eulerr) CairoPNG(file = "tmp1.png") three_inside_fourth <- euler(c("A" = 30, "A&B" = 3, "A&C" = 3, "A&D" = 3, "A&B&C" = 2, "A&B&D" = 2, "A&C&D" = 2, "A&B&C&D" = 1)) plot(three_inside_fourth) dev.off() writeManovaPNG4 <- function() { CairoPNG(file = "tmp2.png") three_inside_fourth <- euler(c("A" = 30, "A&B" = 3, "A&C" = 3, "A&D" = 3, "A&B&C" = 2, "A&B&D" = 2, "A&C&D" = 2, "A&B&C&D" = 1)) plot(three_inside_fourth) dev.off() } writeManovaPNG4()

The on.exit doesn't make any difference-it fails within a function regardless. But on.exit is required for proper use, since if there is a problem with permissions or the network drive goes down, without the on.exit, it leaks the file pointer, since an error in plot will throw an exception and skip the dev.off call.

jolars commented 3 years ago

Ah, now I know what the issue is. You need to call print() directly if you want to save the figure from inside a function since it's not invoked directly when you're not running it interactively.

writeManovaPNG4 <- function() {
  library(Cairo)
  library(eulerr)

  CairoPNG(file = "tmp2.png")

  three_inside_fourth <- euler(c("A" = 30,
                                 "A&B" = 3, "A&C" = 3, "A&D" = 3,
                                 "A&B&C" = 2, "A&B&D" = 2, "A&C&D" = 2,
                                 "A&B&C&D" = 1))
  print(plot(three_inside_fourth))
  dev.off()
}

writeManovaPNG4()
#> png 
#>   2

Created on 2020-12-20 by the reprex package (v0.3.0)

jolars commented 3 years ago

This is not specific to eulerr, by the way, this is the case with almost all implementations of grid-based plotting, including ggplot2 and lattice.