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

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.

Related

How to save plot generated by varImpPlot function (Random Forest) [duplicate]

I plot a simple linear regression using R.
I would like to save that image as PNG or JPEG, is it possible to do it automatically? (via code)
There are two different questions: First, I am already looking at the plot on my monitor and I would like to save it as is. Second, I have not yet generated the plot, but I would like to directly save it to disk when I execute my plotting code.
There are two closely-related questions, and an answer for each.
1. An image will be generated in future in my script, how do I save it to disk?
To save a plot, you need to do the following:
Open a device, using png(), bmp(), pdf() or similar
Plot your model
Close the device using dev.off()
Some example code for saving the plot to a png file:
fit <- lm(some ~ model)
png(filename="your/file/location/name.png")
plot(fit)
dev.off()
This is described in the (combined) help page for the graphical formats ?png, ?bmp, ?jpeg and ?tiff as well as in the separate help page for ?pdf.
Note however that the image might look different on disk to the same plot directly plotted to your screen, for example if you have resized the on-screen window.
Note that if your plot is made by either lattice or ggplot2 you have to explicitly print the plot. See this answer that explains this in more detail and also links to the R FAQ: ggplot's qplot does not execute on sourcing
2. I'm currently looking at a plot on my screen and I want to copy it 'as-is' to disk.
dev.print(pdf, 'filename.pdf')
This should copy the image perfectly, respecting any resizing you have done to the interactive window. You can, as in the first part of this answer, replace pdf with other filetypes such as png.
If you want to keep seeing the plot in R, another option is to use dev.copy:
X11 ()
plot (x,y)
dev.copy(jpeg,filename="plot.jpg");
dev.off ();
If you reach a clutter of too many plot windows in R, use graphics.off() to close all of the plot windows.
If you use ggplot2 the preferred way of saving is to use ggsave. First you have to plot, after creating the plot you call ggsave:
ggplot(...)
ggsave("plot.png")
The format of the image is determined by the extension you choose for the filename. Additional parameters can be passed to ggsave, notably width, height, and dpi.
Like this
png('filename.png')
# make plot
dev.off()
or this
# sometimes plots do better in vector graphics
svg('filename.svg')
# make plot
dev.off()
or this
pdf('filename.pdf')
# make plot
dev.off()
And probably others too. They're all listed together in the help pages.
For the first question, I find dev.print to be the best when working interactively. First, you set up your plot visually and when you are happy with what you see, you can ask R to save the current plot to disk
dev.print(pdf, file="filename.pdf");
You can replace pdf with other formats such as png.
This will copy the image exactly as you see it on screen. The problem with dev.copy is that the image is often different and doesn't remember the window size and aspect ratio - it forces the plot to be square by default.
For the second question, (as others have already answered), you must direct the output to disk before you execute your plotting commands
pdf('filename.pdf')
plot( yourdata )
points (some_more_data)
dev.off() # to complete the writing process and return output to your monitor
If you use R Studio http://rstudio.org/ there is a special menu to save you plot as any format you like and at any resolution you choose
If you open a device using png(), bmp(), pdf() etc. as suggested by Andrie (the best answer), the windows with plots will not pop up open, just *.png, *bmp or *.pdf files will be created. This is convenient in massive calculations, since R can handle only limited number of graphic windows.
However, if you want to see the plots and also have them saved, call savePlot(filename, type) after the plots are drawn and the window containing them is active.
plotpath<- file.path(path, "PLOT_name",paste("plot_",file,".png",sep=""))
png(filename=plotpath)
plot(x,y, main= file)
dev.off()
To add to these answers, if you have an R script containing calls that generate plots to screen (the native device), then these can all be saved to a pdf file (the default device for a non-interactive shell) "Rplots.pdf" (the default name) by redirecting the script into R from the terminal (assuming you are running linux or OS X), e.g.:
R < myscript.R --no-save
This could be converted to jpg/png as necessary
In some cases one wants to both save and print a base r plot. I spent a bit of time and came up with this utility function:
x = 1:10
basesave = function(expr, filename, print=T) {
#extension
exten = stringr::str_match(filename, "\\.(\\w+)$")[, 2]
switch(exten,
png = {
png(filename)
eval(expr, envir = parent.frame())
dev.off()
},
{stop("filetype not recognized")})
#print?
if (print) eval(expr, envir = parent.frame())
invisible(NULL)
}
#plots, but doesn't save
plot(x)
#saves, but doesn't plot
png("test.png")
plot(x)
dev.off()
#both
basesave(quote(plot(x)), "test.png")
#works with pipe too
quote(plot(x)) %>% basesave("test.png")
Note that one must use quote, otherwise the plot(x) call is run in the global environment and NULL gets passed to basesave().
dev.copy(png,'path/pngFile.png')
plot(YData ~ XData, data = mydata)
dev.off()

rgl.postscript when rgl.useNULL = TRUE

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.

export all the content of r script into pdf

I would want to export all the content of r script into pdf. Could it be possible?
I used these commands export, but what I see I just exported graphics
pdf(file = "example.pdf")
dev.off()
Thank you!
setwd("C:/Users/Prat/Desktop/c")
> dir()
[1] "script.R"
> knitr::stitch('script.r')
output file: script.tex
In my folder doesn't appears a script.pdf else a script.tex and a folder with the pictures in pdf
You can do this with the knitr package. Here's a workflow:
Save your script as a file (e.g., myscript.r)
Then run knitr::stitch('myscript.r')
The resulting PDF will be saved locally as myscript.pdf. You can use browseURL('myscript.pdf') to view it.
You can generate html file by using,
knitr::stitch_rhtml('filename.r')
As .tex file is not easily readable but html files can view in any browser easily.
For everyone who is looking for an easy and fast solution, I would propose using the function capture.output (https://www.rdocumentation.org/packages/utils/versions/3.6.2/topics/capture.output) from utils.
One only needs to 1.) capture what ever command one wants to run and assign it to a variable and 2.) then print that variable. Images can be printed along the way as you can see. The example on the webpage I linked above does not use markdown.
Here my example with markdown (this is really all one needs):
```{r, echo = F}
# fake data-set
x = rnorm(50, mean = 3.3, sd=1)
y = rnorm(50, mean = 3.1, sd=0.9)
z = rnorm(50, mean = 3.2, sd=1.1)
# create dataframe
df <- data.frame(x, y, z)
# adding a graphic
plot(df$x, df$y)
# create a model as example
linearMod <- lm(y ~ x + z, data=df)
# all one needs to capture the output!!:
bla <- capture.output(summary(linearMod))
print(bla)
```
Remark: if one also wants to print the command, that is also easy. Just replace "echo = F" with "warning = F" or remove the text altogether if you also wanna have the warnings printed, in case there are any.
I was having the same issue, but I realized I was working in R 4.1 and ignored the warning that knitr was created using R 4.2. However after updating my R version, I was also just getting a .tex file but when I read the .log file I found the error "sh: pdflatex: command not found."
I used this suggestion with success:
Have you installed a LaTeX distribution in your system? For rmarkdown,
tinytex is recommended, you would need to install the R package and
then the TinyTex distribution.
install.packages('tinytex')
tinytex::install_tinytex()
Make sure you not only install the package but also run that second command tinytex::install_tinytex() as I made that mistake also before finally getting the program to create a pdf file.
Here is the link to the site where I found this method.
https://community.rstudio.com/t/knitting-error-pdflatex-command-not-found/139965/3
Please use the below set of codes (you need to modify it according to your dataset/data-frame name).
library(gridExtra)
library(datasets)
setwd("D:\\Downloads\\R Work\\")
data("mtcars") # Write your dataframe name that you want to print in pdf
pdf("data_in_pdf.pdf", height = 11, width = 8.5)
grid.table(mtcars)
dev.off()
Thanks.

R eps export and import into Word 2010

I'm having trouble with exporting eps files from R and importing into Word 2010.
I'm using ggplot2 plots, eg
library(ggplot2)
p <- qplot(disp,hp,data=mtcars) + stat_smooth()
p
Even after calling setEPS() neither of the following produce files which can be successfully imported.
ggsave("plot.eps")
postscript("plot.eps")
print(p)
dev.off()
The strange thing is that if I produce the plot using File -> Save As -> Postscript from the menu in the GUI, it can be imported correctly. However, when the Word document is subsequently exported as a pdf, the fonts in the graphic are a little jagged.
So my questions are:
What combination of (ggsave/postscript) settings allows me to produce eps files that can be imported into Word 2010?
How can I ensure the fonts remain clear when the Word document is exported as a pdf?
Update
After more investigation I have had more luck with cairo_ps to produce the plots. However, no text shows up when imported into Word.
Furthermore, after checking the various eps outputs (cairo_ps, save from the GUI, ggsave) in a latex document, it seems like the eps import filter in Word quite poor as the printed/pdf output doesn't match the quality of the latex'd document. The ggsave version (which uses postscript) did have some issues with colours that the other two methods didn't have though.
The conclusion is that this is a Word issue and therefore fortune(109) does not apply. I'd be happy to be proven otherwise, but I'll award the answer and the bounty to whoever can provide the commands that can replicate the output from the GUI in command form.
This worked for me... following advice in the postscript help page:
postscript("RPlot.eps", height = 4, width = 4, horizontal = FALSE, onefile = FALSE,
paper = "special")
library(ggplot2)
p <- qplot(disp,hp,data=mtcars) + stat_smooth()
p
#geom_smooth: method="auto" and size of largest group is <1000, so using loess. Use 'method = x' to #change the smoothing method.
#Warning message:
#In grid.Call.graphics(L_polygon, x$x, x$y, index) :
# semi-transparency is not supported on this device: reported only once per page
dev.off()
#quartz
# 2
The funny stuff at the end puts you on notice that this is only a Mac-tested solution, so far anyway.
Edit: I just tested it with R version 2.15.1 (2012-06-22) -- "Roasted Marshmallows": Platform: i386-pc-mingw32/i386 (32-bit) and MS Word 2007 in Win XP and it worked. Commands were Insert/Picture.../select eps format/select file.
Edit2: There is another method for saving besides directly using the postscript device. The savePlot method with an "eps" mode is available in Windows (but not in the Mac). I agree that the fonts are not as smooth as they appear on a Mac but I can discern no difference in quality between saving with savePlot and using save as from an interactive window.
savePlot(filename = "Rplot2", type = "eps", device = dev.cur(), restoreConsole = TRUE)
savePlot calls (.External(CsavePlot, device, filename, type, restoreConsole))
I solved the problem with exporting .eps files from R and importing into Word 2010 on Windows 7 using the colormodel="rgb" option (defaults to "srgb") of the postscript command.
postscript("RPlot.eps", height = 4, width = 4, horizontal = FALSE,
paper = "special", colormodel = "rgb")
library(ggplot2)
p <- qplot(disp,hp,data=mtcars) + stat_smooth(se=FALSE, method="loess")
p
dev.off()
You are probably better of using wmf as a format which you can create on Windows.
Word indeed doesn't support EPS very well.
A better solution is to export your graphs to Word or Powerpoint directly in native Office format. I just made a new package, export, that does exactly that, see
https://cran.r-project.org/web/packages/export/index.html and
for demo
https://github.com/tomwenseleers/export
Typical syntax is very easy, e.g.:
install.packages("export")
library(export)
library(ggplot2)
qplot(Sepal.Length, Petal.Length, data = iris, color = Species,
size = Petal.Width, alpha = I(0.7))
graph2doc(file="ggplot2_plot.docx", width=6, height=5)
graph2ppt(file="ggplot2_plot.pptx", width=6, height=5)
Output is vector format and so fully editable after you ungroup your graph in Word or Powerpoint. You can also use it to export statistical output of various R stats objects.
You can use R studio to knit html files with all of your plots and then open HTML files with Word.
knitr tutorial

R - Keep log of all plots

I do a lot of data exploration in R and I would like to keep every plot I generate (from the interactive R console). I am thinking of a directory where everything I plot is automatically saved as a time-stamped PDF. I also do not want this to interfere with the normal display of plots.
Is there something that I can add to my ~/.Rprofile that will do this?
The general idea is to write a script generating the plot in order to regenerate it. The ESS documentation (in a README) says it well under 'Philosophies for using ESS':
The source code is real. The objects are realizations of the
source code. Source for EVERY user modified object is placed in a
particular directory or directories, for later editing and
retrieval.
With any editor allows stepwise (or regionwise) execution of commands you can keep track of your work this way.
The best approach is to use a script file (or sweave or knitr file) so that you can just recreate all the graphs when you need them (into a pdf file or other).
But here is the start of an approach that does the basics of what you asked:
savegraphs <- local({i <- 1;
function(){
if(dev.cur()>1){
filename <- sprintf('graphs/SavedPlot%03d.pdf', i)
dev.copy2pdf( file=filename )
i <<- i + 1
}
}
})
setHook('before.plot.new', savegraphs )
setHook('before.grid.newpage', savegraphs )
Now just before you create a new graph the current one will be saved into the graphs folder of the current working folder (make sure that it exists). This means that if you add to a plot (lines, points, abline, etc.) then the annotations will be included. However you will need to run plot.new in order for the last plot to be saved (and if you close the current graphics device without running another plot.new then that last plot will not be saved).
This version will overwrite plots saved from a previous R session in the same working directory. It will also fail if you use something other than base or grid graphics (and maybe even with some complicated plots then). I would not be surprised if there are some extra plots on occasion that show up (when internally a plot is created to get some parameters, then immediatly replaced with the one of interest). There are probably other things that I have overlooked as well, but this might get you started.
you could write your own wrapper functions for your commonly used plot functions. This wrapper function would call both the on-screen display and a timestamped pdf version. You could source() this function in your ~/.Rprofile so that it's available every time you run R.
For latice's xyplot, using the windows device for the on-screen display:
library(lattice)
my.xyplot <- function(...){
dir.create(file.path("~","RPlots"))
my.chart <- xyplot(...)
trellis.device(device="windows",height = 8, width = 8)
print(my.chart)
trellis.device(device = "pdf",
file = file.path("~", "RPlots",
paste("xyplot",format(Sys.time(),"_%Y%m%d_%H-%M-%S"),
".pdf", sep = "")),
paper = "letter", width = 8, height = 8)
print(my.chart)
dev.off()
}
my.data <- data.frame(x=-100:100)
my.data$y <- my.data$x^2
my.xyplot(y~x,data=my.data)
As others have said, you should probably get in the habit of working from an R script, rather than working exclusively from the interactive terminal. If you save your scripts, everything is reproducible and modifiable in the future. Nonetheless, a "log of plots" is an interesting idea.

Resources