rgl.postscript when rgl.useNULL = TRUE - r

Shouldn't rgl.postscript() work for a headless server, i.e. when options(rgl.useNULL = TRUE)? I know that rgl.snapshot() won't work.
library(rgl)
options(rgl.useNULL = TRUE)
open3d()
x <- sort(rnorm(1000))
y <- rnorm(1000)
z <- rnorm(1000) + atan2(x, y)
plot3d(x, y, z, col = rainbow(1000))
rgl.postscript("test.pdf",fmt="pdf")
This gives me "In rgl.postscript("test.pdf", fmt = "pdf") : Postscript conversion failed".

It could do so in some cases, but currently it doesn't. One issue is that if rgl is started with the null device, it won't even link in the OpenGL functions, and rgl.postscript() uses some of them.
Edit: Sorry, the "no linking" is what I'd like. Currently it does need to link, but it won't run the initialization code, so it should work in contexts (e.g. a headless server) where no display is available.
On a headless server you could use Xvfb for a "virtual frame buffer". I don't have a lot of experience with it, but I think I've heard that it doesn't handle rgl.snapshot properly. I'd expect rgl.postscript to work.
In principle, you could also render in WebGL, and then use some other tool to convert the output to your desired format. I don't know if any such tools exist.

Related

R Need to restart RStudio to view and save in a file using dev.copy() and dev.off()

I am trying to create a plot and eventually save it as a file. But because I am making a lot of changes and want to test it out, I want to be able to view and save the plot at the same time. I have looked at this page to do what I want to do but in my system, it does not seem to be working as it is supposed to.
Here are my codes:
png('Save.png')
sample.df <- data.frame(group = c('A','B','A','C','B','A','A','C','B','C','C','C','B'),
X = c(2,11,3,4,1,6,3,7,5,9,10,2,8),
Y = c(3,8,5,2,7,9,3,6,6,1,3,4,10))
plot(Y ~ X, data = sample.df)
dev.copy(png, 'Save.png')
dev.off()
There are several issues (I am new to R so I might be missing something entirely):
(1) When I use png(), I cannot view the plot in RStudio so I used dev.copy() but it does not allow me to view my plot in R studio
(2) Even after I use dev.off(), I cannot view the saved file until I close the RStudio (says "Windows Photo Viewer can't open this picture because the picture is being edited in another program"). I need to restart every time so it is very inconvenient.
What am I doing wrong and how could I view and view saved file without restarting RStudio every time? Thank you in advance!
Addition
Based on Love Tätting's comments, when I run dev.list(), this is what I get.
> png('Save.png')
>
> sample.df <- data.frame(group = c('A','B','A','C','B','A','A','C','B','C','C','C','B'),
+ X = c(2,11,3,4,1,6,3,7,5,9,10,2,8),
+ Y = c(3,8,5,2,7,9,3,6,6,1,3,4,10))
>
> plot(Y ~ X, data = sample.df)
>
> dev.copy(png, 'Save.png')
png
3
> dev.off()
png
2
> dev.list()
png
2
> dev.off()
null device
1
> dev.list()
NULL
Why do I not get RStudioGD?
RStudio has its own device, "RStudioGD". You can see it with dev.list(), where it by default is the first and only one.
R's design for decoupling rendering and backend is by the abstraction of devices. Which ones you can use is platform and environment dependent. dev.list() shows the stack of current devices.
If I understand your problem correctly you want to display the graph first in RStudio, and then decide whether you want to save it or not. Depending on how often you save th image you could use the 'export' button in the plot pane in RStudio and save it manually.
Otherwise, your choice of trying to copy it would be the obvious one for me as well.
To my knowledge the device abstraction in R does not allow one to encapsulate the device as an object, so one for example could make it an argument to a function that does the actual plot. Since dev.set() takes an index as argument, passing the index as argument will be dependent on state of the stack of devices.
I have not come up with a clean solution to this myself and have sometimes retorted to bracketing the plot rendering code with a call to a certain device and saving it right after, and switching device depending on a global.
So, if you can, use RStudios export functionality, otherwise an abstraction would need to maintain the state of the global stack of devices and do extensive testing of its state as it is global and you cannot direct a plot call to a certain device, it simply plots to the current device (to my knowledge).
Edit after OP comment
It seems that it is somewhat different behaviour you are experiencing if you cannot watch the file after dev.off, but also need to quit RStudio. For some type of plot frameworks there is a need to call print on the graphical object to have it actually print to the file. Perhaps this is done by RStudio at shutdown as part of normal teardown procedures of open devices? In that ase the file should be empty if you forcibly look in its contents before quiting RStudio.
The other thing that sometimes work is to call dev.off twice. I don't know exactly why, but sometimes more devices get created than I have anticipated. After you have done dev.off, what does dev.list show?
Edit after OP's edit
I can see that you do, png(); dev.copy(); dev.off(). This will leave you with one more device opened than closed. You will still have the first graphics device that you started open as can be seen when you do the listing. You can simply remove dev.copy(). The image will be saved on dev.off() and should be able to open from the filesystem.
As to why you cannot see the RStudio graphics device, I am not entirely sure. It might be that other code is messing with your device stack. I would check in a clean session if it is there to make sure other code isn't tampering with the device stack. From RStudio forums and other SO questions there seem to have been plot pane related problems in RStudio that have resolved after updating RStudio to the latest. If that is a viable solution for you I would try that.
I've just added support for RStudio's RStudioGD device to the developer's version of R.devices package (I'm the author). This will allow you to do the following in RStudio:
library("R.devices")
sample.df <- data.frame(
group = c('A','B','A','C','B','A','A','C','B','C','C','C','B'),
X = c(2,11,3,4,1,6,3,7,5,9,10,2,8),
Y = c(3,8,5,2,7,9,3,6,6,1,3,4,10)
)
figs <- devEval(c("RStudioGD", "png"), name = "foo", {
plot(Y ~ X, data = sample.df)
})
You can specify any set of output target types, e.g. c("RStudioGD", "png", "pdf", "x11"). The devices that output to file will by default write the files in folder figures/ with filenames as <name>.<ext>, e.g. figures/foo.png in the above example.
The value of the call, figs, holds references to all figures produced, e.g. figs$png. You can open them directly from R using the operator !. For example:
> figs$png
[1] "figures/foo.png"
> !figs$png
[1] "figures/foo.png"
The latter call should show the PNG file using your system's PNG viewer.
Until I submit these updates to CRAN, you can install the developer's version (2.15.1.9000) as:
remotes::install_github("HenrikBengtsson/R.devices#develop")

knitr and plotting neural networks

I'm trying to plot some neural network outputs, but I'm not getting any result. Plotting normal stuff like plot(iris) works fine, but there's something about the neuralnetwork() object that doesn't seem to plot the same way.
My file looks like:
---
title: "stack"
author: "stack"
date: "today"
output:
pdf_document: default
html_document: default
---
```{r}
library(neuralnet)
AND <- c(rep(0,3),1)
binary.data <- data.frame(expand.grid(c(0,1), c(0,1)), AND)
net <- neuralnet(AND~Var1+Var2, binary.data, hidden=0,err.fct="ce", linear.output=FALSE)
plot(net)
```
And I get no output. Same file plots other stuff just fine. Any thoughts?
This issue has been reported and answered before in the rmarkdown repository. Here I'm only trying to explain the technical reason why it didn't work.
From the help page ?neuralnet::plot.nn:
Usage
## S3 method for class 'nn'
plot(x, rep = NULL, x.entry = NULL, x.out = NULL,
....
Arguments
...
rep repetition of the neural network. If rep="best", the repetition
with the smallest error will be plotted. If not stated all repetitions
will be plotted, each in a separate window.
From the source code (v1.33):
> neuralnet:::plot.nn
function (x, rep = NULL, x.entry = NULL, x.out = NULL, radius = 0.15,
....
{
....
if (is.null(rep)) {
for (i in 1:length(net$weights)) {
....
grDevices::dev.new()
plot.nn(net, rep = i,
....
}
}
I have omitted the irrelvant information using .... above. Basically if you do not specify rep, neuralnet:::plot.nn will open new graphics devices to draw plots. That will break knitr's graphics recording, because
It opened graphical devices but didn't request them to turn on recording (via dev.control(displaylist = 'enable'));
knitr uses its own device to record graphics by default; if users opened new devices, there is no guarantee that new plots can be saved by knitr. In general, I'd discourage manipulating graphical devices in plotting functions.
I'm not an author of the neuralnet package, but I'd suggest the authors drop dev.new(), or at least make it conditional, e.g.
if (interactive()) grDevices::dev.new()
I guess the intention of the dev.new() call was probably to show plots in new windows, but there is really no guarantee that users can see windows. The default graphical device of an interactive R session is a window/screen device (if available, e.g. x11() or quartz()), but it is quite possible that the default device has been changed by users or package authors.
I suggest the condition interactive() because for a non-interactive R session, it probably does not make much sense to open new (by default, off-screen) devices.
I think the issue is that for objects of class nn, plot uses a parameter rep. If rep is not defined, all repetitions are plotted in separate windows (when run outside of RMarkdown). If rep = "best", only the plot with the smallest error is generated. So this should work:
```{r}
library(neuralnet)
AND <- c(rep(0,3),1)
binary.data <- data.frame(expand.grid(c(0,1), c(0,1)), AND)
net <- neuralnet(AND~Var1+Var2, binary.data, hidden=0,err.fct="ce",
linear.output=FALSE)
plot(net, rep = "best")
```
See ?plot.nn.

Saving plot.ly image to RData file

I create a plot_ly image using:
MilesPlotly <- plot_ly(x = TripDetails$TotalDistanceMiles, type = "histogram")
I then want to save it to an RData file to simply open it later (hence pre-compute)
save(MilesPlotly, file = "my/path/here/myPlot.RData")
Later on I want to simply plot it by doing
load(my/path/here/myPlot.RData)
MilesPlotly
Now, this works on Mac. This does not work on my Ubuntu server on AWS.
Does anyone have any ideas why the discrepancy? The plotly version on both is 3.6.0.
Your code doesn't work on my windows environment and plotly_build() solves it (I'm not sure this code works on your env).
MilesPlotly <- plot_ly(x = TripDetails$TotalDistanceMiles, type = "histogram")
MilesPlotly <- plotly_build(MilesPlotly)
save(MilesPlotly, file = "my/path/here/myPlot.RData")
load("my/path/here/myPlot.RData")
MilesPlotly
After some tweaking, I realized I needed to do two things:
1) I updated R to 3.3.1
2) You need to "build" the plot before saving it. That means:
MilesPlotly <- plot_ly(x = TripDetails$TotalDistanceMiles, type = "histogram") %>%
build()

opening a plotly plot in a browser instead of a viewer in rstudio

I'm looking for a way to render my plot_ly plot directly to a browser in stead of r-studios default viewer. I've searched the plotly documentation but I only see a reference to the default behavior of opening the plot to a browser when running r from a terminal.
Does anyone know how to open to a browser window by default? Maybe a parameter to the plotly layout() option?
Alright I found a simple solution in the related questions section next to my original question. Sorry I didn't find it before. stackoverflow.com/questions/36868743 .
Setting: options(viewer=NULL) in the script disables the viewer and opens my plot in the browser.
Not really elegant and how to turn the default viewer back on is still a little mystery.
An example from this site might help:
http://www.statsblogs.com/2014/02/06/protected-online-r-and-plotly-graphs-canadian-and-u-s-maps-old-faithful-with-multiple-axes-overlaid-histograms/
library(plotly)
p <- plotly(username="MattSundquist", key="4om2jxmhmn")
library(maps)
data(canada.cities)
trace1 <- list(x=map(regions="canada")$x,
y=map(regions="canada")$y)
trace2 <- list(x= canada.cities$long,
y=canada.cities$lat,
text=canada.cities$name,
type="scatter",
mode="markers",
marker=list(
"size"=sqrt(canada.cities$pop/max(canada.cities$pop))*100,
"opacity"=0.5)
)
response <- p$plotly(trace1,trace2)
url <- response$url
filename <- response$filename
browseURL(response$url)
The main take home being browseURL(response$url). Notice the sign in as well.

Saving rgl 3D scene to u3d (for .pdf integration)

I have a 3D scene generated with the R rgl package.
I can save it in RTL and OBJ format via the rgl functions, but these functions don't support colors.
I can save it in WebGL, but then I can't find a WebGL to .u3d converter, nor any way to insert WebGL content in a .pdf file (generated with LaTeX).
I can save it in PLY format and then export to .u3d (e.g. using Meshlab), but it gives me the following error:
Error in if (sum(normals[1:3, it[j, i]] * normal) < 0) normals[, it[j, :
missing value where TRUE/FALSE needed
Which I really don't know how to solve.
Here is an example file to reproduce the problem.
To reproduce simply download the file in the working directory, execute R and run:
library(rgl)
load("alps3d.Rdata") #This loads the alps3d variable
plot3d(alps3d)
writePLY("alps3d.ply")
How can I save the 3d scene in a format which can be itegrated in a .pdf using LaTeX?
You should try writeASY(). It writes for Asymptote, which can produce PRC rather than U3D, but may be good enough. I tried your sample scene, and it takes about 5 minutes to load the result in Acrobat Reader, but it eventually loads and works.
writeASY() is a recent addition to rgl; you'll need to get it from the R-Forge or Github copies.
You can use rgl.postscript, which allows to export to various formats, including pdf.
Well, the result is not terrific, but that should depend on the type of plot.
> x <- y <- seq(-10, 10, length = 20)
> z <- outer(x, y, function(x, y) x^2 + y^2)
> persp3d(x, y, z, col = 'lightblue')
> rgl.postscript("persp3d.pdf", "pdf")
You can also export to tex, allowing to do some manual modifications.

Resources