rgl: how to produce higher resolution snapshots? - r

For a book, I want to show two rgl images side-by-side, as in the image below. But the publisher wants images with at least 300 dpi resolution.
I created this using the code below to produce two separate images with rgl.snapshot() and then combined them into a single image with some other software.
How can I amend the code below to save each image with higher
resolution? The images I get are ~ 256 x 256 pixels, I think with 72 dpi resolution.
Is there a different device driver I could use with rgl.snapshot?
Is there some way to compose these into a single image using R?
data(randu)
# Figure 9.15 - 3D plots
library(rgl)
with(randu, plot3d(x, y, z, size=6, axes=FALSE,
xlab = "", ylab = "", zlab = ""))
box3d(col="gray")
# left panel
rgl.snapshot("randu0.png")
# right panel
rgl.viewpoint(theta = -3.8, phi = 3.8, fov = 0, zoom = 0.7)
rgl.snapshot("randu.png")

Save in eps format with rgl.postscript. Then convert to png with GhostScript (gs).
data(randu)
library(rgl)
with(randu, plot3d(x, y, z, size=6, axes=FALSE,
xlab = "", ylab = "", zlab = ""))
box3d(col="gray")
# save in eps format
rgl.postscript("randu.eps")
# convert to png
cmd <-
"gs -dSAFER -dBATCH -dNOPAUSE -dEPSCrop -sDEVICE=png16m -r600 -sOutputFile=randu.png randu.eps"
system(cmd)
You can use ImageMagick to append two images.

Related

Adding a Vertical Plane to a 3d Scatter plot in rgl or scatter3D

I am using the packages rgl and plot3D to plot 3 dimensional data in a scatter plot. my data looks as follows:
install.packages("rgl")
library(rgl)
x <- Kg$GBMVP_SD
y <- Kg$GBMVP_Ret
z <- Kg$Asset_No
K<- as.matrix(Kg$GRN_No)
RF<- as.matrix(Kg$Risk_Free)
scatter3D(x , y , z , colvar = K,
pch = 16, cex = 1.5, xlab = "GMVP Standard Deviation", ylab = "GMVP Return",
zlab = "Total No of Assets in Portfolio", clab = c("Green Asset No"),
main = "Global Minimum Variance Portfolio(GMVP) Return and Standard Deviation vs No of Green Assets ", ticktype = "detailed",
colkey = list(length = 0.5, width = 0.5, cex.clab = 0.75))
which gives me:
I am trying to add a vertical plane to this where for x and z as specified above, the y is equal to RF, which is all one value. I have tried the rgl package with no luck, as all fit regression planes and when I use different z values in the plane as that specified for the scatter, it doesn't plot. I am trying to avoid using the scatterplot3d package due to the better graphics of the other packages, but will do if there is on other option. Any help is appreciated.

Define plot elements size in mm (R)

I am preparing figures in R for submission to a journal. Required formatting is given in mm (line width = 0.5mm, symbols = 3mm, etc).
I know how to define the figure size in mm, and to manage line width and symbol size with respectively lwd and cex, either in par() or within the plot function. I also found how to convert points to mm. However I don't know how to define line weight, text size, etc. precisely, and not "scaling up" as usual (eg. I want lwd = 0.5mm, not lwd = 1.2 x the default size).
I hope I am clear enough =)
Here is my code :
jpeg(paste('path-to-figure.jpg'), width=15, height=7)
plot(x, y, main = 'TITLE', xlab = "X NAME",ylab = 'Y NAME', ylim = c(0,180), xlim = c(0, 4)pch = 1)
dev.off()
Many Thanks !
Line widths in the standard jpeg, png etc. graphics devices are defined in 1/96 of an inch. See https://stat.ethz.ch/R-manual/R-devel/library/grDevices/html/png.html . The same is true for pdf but may vary for other devices. 0.5 mm = 0.5 / 25.4 * 96 = 1.890 96ths of an inch. So you would use lwd = 1.89.
You could also consider using ggplot2 since size within that is in mm anyway.
E.g.
ggplot(my_data, aes(x, y)) + geom_line(size = 0.5)

Changing text size of 3d plot, R

I have a problem changing the text size of a 3d plot I generated with the package rgl. Everything works fine, but I can't effectively change the cex and size properties of an 3d object when rendering it in shiny, with the renderWebGL
library(rgl)
plot3d(x, y, z, xlab ="x", ylab ="y", zlab ="z")
texts3d(x, y, z, rownames(data))
Any help is highly appreciated! Best Regards.
Brecht
You can scale the text (including axis labels) by changing the "cex" rgl parameter, by calling the function par3d. The "cex" rgl parameter is different from the "cex" parameter in base graphics.
For example, if you want to magnify the text in your plot by a factor of 2, then you can call:
par3d(cex=2.0)
with(iris,
plot3d(Sepal.Length, Sepal.Width, Petal.Length,
type="s", col=as.numeric(Species)))
Note that calling par3d opens a plotting window. Calling a plotting function creates a plot in that same window. You have to call par3d every time you create a new plot. The function par3d can also change many other rgl parameters.
I ran into similar problems with library plot functions from PerformanceAnalytics. I would advise to get the code for the function by typing plot3d in the console and looking at the original plot functions inside.
It might be the case that the plot3d function doesn't pass a cex option forward, so you can also copy the function and modify it to make it your own myplot3d function or something like that.
For anyone still trying to address this issue, the plot3D package takes care of this nicely now.
See the following reproducible code.
# Load plot3D package
library(plot3D)
Using the iris dataset, let's make a 3D graph. See our use of cex, cex.main, and cex.lab at the end, which allow us to multiply text size, all within the package.
scatter3D(
x = iris$Sepal.Length,
y = iris$Sepal.Width,
z = iris$Petal.Length,
# Add a nice background
bty = "u",
col.grid = "darkgrey",
col.panel = "black",
# Specify Labels
main = "My graph",
clab = "Petal\nLength",
xlab = "\nSepal Length",
ylab = "\nSepal Width",
zlab = "\nPetal Length",
# Adjust label sizing
cex = 2, # Multiply dot size by 2
cex.main = 2, # Multiply the size of main title text by 2
cex.lab = 2) # Multiply size of axis label text by 2
Or, we can shrink the text size back to normal, here:
scatter3D(
x = iris$Sepal.Length,
y = iris$Sepal.Width,
z = iris$Petal.Length,
# Add a nice background
bty = "u",
col.grid = "darkgrey",
col.panel = "black",
# Specify Labels
main = "My graph",
clab = "Petal\nLength",
xlab = "\nSepal Length",
ylab = "\nSepal Width",
zlab = "\nPetal Length",
# Adjust label sizing
cex = 1, # Multiply dot size by 2
cex.main = 1, # Multiply the size of main title text by 2
cex.lab = 1) # Multiply size of axis label text by 2
Not the OP situation but if you need to change the text size on a rgl plot and your text is a LaTeX expression you have to pass the text size parameter (cex) to the corresponding function.
For example,
library(rgl)
library(magrittr)
iris %>%
{points3d('x'=.$Sepal.Length, 'y'=.$Sepal.Width, z=.$Petal.Length)}
title3d(main=NULL, sub=setName,
xlab=latex2exp::TeX(r"($\phi_{\pi})"),
ylab=latex2exp::TeX(r"($\phi_{X}$)"),
zlab=latex2exp::TeX(r"($\psi_{B}$)"),
cex=4)
Notice the cex argument in title3d() which is passed to plotmath3d() which actually draws the LaTeX expression into a PNG file that is then paste on the final plot. See the documentation for plotmath3d for details but cex is a number that scales the text size.

output high resolution filled.contour figure in R

I am trying to save my filled.contour plots as a high resolution(>600dpi) piture(png, jpeg....) in Rstudio.
However, when I use the "export" function in the interface of Rstudio, the resolution is very low(the figure is only around 20kb).
Then I tried to use "PNG" command to save my plots, but I failed.
May I ask is there anyone knows how to achieve this?
Really appreciate for your kind help!
I assume you want to do this to maintain resolution when the image is rendered at a very large scale. To achieve that using the png(...) function, you have to set the size (height and width parameters) and also the resolution in ppi (res parameter). So the code below creates a png file of an 11 X 8.5 inch image at 600 ppi, or 6600 X 5100 pixels. The file is 435KB.
# open the png graphics device
png("volcano.png",res=600,height=8.5,width=11,units="in")
## the following is taken verbatim from the filled.contour(...) documentation
x <- 10*1:nrow(volcano)
y <- 10*1:ncol(volcano)
filled.contour(x, y, volcano, color=terrain.colors,
plot.title = title(main = "The Topography of Maunga Whau",
xlab = "Meters North", ylab = "Meters West"),
plot.axes = { axis(1, seq(100, 800, by = 100))
axis(2, seq(100, 600, by = 100)) },
key.title = title(main = "Height\n(meters)"),
key.axes = axis(4, seq(90, 190, by = 10))) # maybe also asp = 1
mtext(paste("filled.contour(.) from", R.version.string),
side = 1, line = 4, adj = 1, cex = .66)
##
# close the graphic device
dev.off()
If you expect to render this at a physical size greater than 11 X 8.5, you would need to generate the png at the appropriate size.

Insert formula in plot with easy and pretty code

Gnu R ships with a very odd way to note formulas and symbols. It is often discussed here and mentioned in the R helppage ?plotmath. For anyone who ever wrote LaTeX the code for a simple formula in R looks unreadable and is errorprone to write.
Is there a better way to annotate with formulas? Is there a function like tex2r("x_2") that will generate the strange code?
edit:
I am looking for a solution without TikZdevice, because TikZdevice is still very fragile and the printoout does not look exactly the same.
With the tikzDevice package (currently available only from the CRAN archive) you can use straight-up LaTeX markup to annotate your plots. (The package comes with a beautiful vignette that'll get you up and running).
The example below was lifted directly from this page, which also displays the figure it produces:
require(tikzDevice)
tikz('normal.tex', standAlone = TRUE, width=5, height=5)
# Normal distribution curve
x <- seq(-4.5,4.5,length.out=100)
y <- dnorm(x)
# Integration points
xi <- seq(-2,2,length.out=30)
yi <- dnorm(xi)
# plot the curve
plot(x,y,type='l',col='blue',ylab='$p(x)$',xlab='$x$')
# plot the panels
lines(xi,yi,type='s')
lines(range(xi),c(0,0))
lines(xi,yi,type='h')
#Add some equations as labels
title(main="$p(x)=\\frac{1}{\\sqrt{2\\pi}}e^{-\\frac{x^2}{2}}$")
int <- integrate(dnorm,min(xi),max(xi),subdivisions=length(xi))
text(2.8, 0.3, paste("\\small$\\displaystyle\\int_{", min(xi),
"}^{", max(xi), "}p(x)dx\\approx", round(int[['value']],3),
'$', sep=''))
#Close the device
dev.off()
# Compile the tex file
tools::texi2dvi('normal.tex',pdf=T)
I just found a package that does exactly what OP was asking for: latex2exp and in there the fuction TeX.
E.g.:
library(latex2exp)
library(berryFunctions)
set.seed(1)
milk <- data.frame(Datum = as.Date(rep(seq(17500, 18460, by = 30), each = 30), origin = "1970-01-01"),
Milch = abs(rnorm(990, mean = 20, sd = 8)))
X11(width = 12, height = 7)
par(mar = c(3,5.5,3,1))
with(milk, plot(Datum, Milch, pch = "-", cex=1.5, col = rgb(red = 0, green = 0.5, blue = 0.5, alpha = 0.7),
xaxt = "n", xlab = "", ylab = "",
main = "Milchleistung am Wolkenhof"))
title(ylab = TeX("Milchmenge $\\,$ $\\left[\\frac{\\mathrm{kg}}{\\mathrm{Kuh} \\cdot \\mathrm{Tag}}\\right]$"), line = 2.5)
monthAxis()
yields:
Edit: Now there is a space between "Milchmenge" and the left bracket "[", but I didn't want to upload a new picture therefore.

Resources