I have made a beautiful plot in R to be used in a scientific journal. According to the journal's specifications, I need an eps file format with embedded fonts. Since R does not export eps files with embedded fonts, I am using the base graphics call embedFonts() to convert it. However, this call is changing the bounding box of my figure. In this simple example below, the white space is cropped. In my OCD-adjusted publication-quality plot, white space is added because I've already adjusted it perfectly to the edges.
I want the fonts to be embedded, but everything else to stay the same!
Here is an example:
setEPS()
postscript(file = "~/Desktop/test.eps", family = "Helvetica", colormodel = "srgb", width = 5, height = 3)
plot(x = 1:10, y = 1:10, col = "red", main = "Keep everything the same but embed my fonts!")
dev.off()
embedFonts(file = "/Users/athena/Desktop/test.eps", format = "eps2write", outfile = "/Users/athena/Desktop/stupid.eps")
So far I have:
- installed ghostscript using homebrew: $ brew install ghostscript
- learned that embedFonts needs FULL paths, no tilda's allowed
- specified the format as "eps2write" because the default "ps2write" changes it to a postscript
I spent so much effort on "reproducible research" with open data, open code, open journal, bla bla bla... I really don't want to have to make my final figures using illustrator conversion or something :(
The reason this happens is because embedFonts internally calls Ghostscript which in turn tries to act smart by fitting an "optimal" bounding box by trimming out some of the surrounding white space.
We can prevent that by drawing an invisible box around the perimeter of our 5inx3in drawing area in R. Just add one more line to your code snippet:
setEPS()
postscript(file = "~/Desktop/test.eps", family = "Helvetica", colormodel = "srgb", width = 5, height = 3)
plot(x = 1:10, y = 1:10, col = "red", main = "Keep everything the same but embed my fonts!")
box(which="outer", col="white")
dev.off()
embedFonts(file = "/Users/athena/Desktop/test.eps", format = "eps2write", outfile = "/Users/athena/Desktop/stupid.eps")
Another way to go about this is Jonathan's answer here which basically uses sed to read in Bounding Box info from the input file and writes it to the output file: http://r.789695.n4.nabble.com/eps-file-with-embedded-font-td903387.html as pointed out by #neilfws in a comment above.
Related
I'm trying to make a png in R where I can vary the resolution without changing the apparent height of the text and it is not working.
Here is my code
drawbox <- function(res, ps=12, textcex=1) {
png(file="test.png",width=6,height=3, units="in", res=res, bg="transparent", pointsize=ps)
plot(x=c(0,1),y=c(0,1),type="n",xaxs = 'i',yaxs = 'i',axes=FALSE)
text(x=0.5, y=0.5, adj=c(0.5,0.5), labels="Some text", cex=textcex*6)
dev.off()
}
then this makes a very different size of text
drawbox(res=300, ps=12, textcex=1)
than this
drawbox(res=100, ps=12, textcex=1)
but isn't that the point of the pointsize argument, that this doesn't happen?
Note: I need base graphics here, other packages lack the flexibility to allow me to make what I want to make.
If I mess around with that textcex parameter I can get things to work, but that's annoying.
Consider the following plot:
q1 <- c(1000000.0, 908364.8, 876009.1, 847892.8, 824808.3, 805416.2, 785266.2, 770997.1, 753908.6, 744599.9, 706777.6, 674659.9, 634654.4, 601440.4, 568259.7, 535361.3, 493679.9, 465526.5, 429766.6, 395244.7, 361483.2, 332136.6, 308574.5, 285500.6, 262166.2 ,237989.0 , 210766.1, 188578.1, 166762.3 , 140399.8 ,114865.5)
plot(q1, type = "l", lty = 1, lwd = 2, col = "darkolivegreen3", ylim = c(0,4*10^6))
As you can somewhat see on the graph, the line is not drawn perfectly, but has some "chainsaw" imperfections.. Is there a parameter or a line type that could fix this?
Thanks!
Anti-aliasing and other issues related to image rendering is controlled by the device you carry out the plotting on. On a windows system please refer to the ?windows help page for options and information. Unfortunately there doesn't seem to be any settings for anti-aliasing so then I guess it comes down to you graphics drivers. In other words, there is no quick fix.
However, you can try plotting to a file with png or jpeg instead. Even better is to plot to a vectorized file, such as pdf or svg where the concept of aliasing doesn't even apply (it is left to the device you view the file in, e.g. acrobat reader).
I have several images in a Sweave report that look like this:
They are created by a function with a code akin to this:
<<fig = T>>=
barplot(prop.table(table(x, y), margin = 2) * 100,
border = F, xlab = '', ylab = '', las = 2)
#
I want to compress the y-axis, so my plot looks something like this (without the label distortion):
The only way I was able to get this was by using png() with a custom height parameter and then using the image file on LaTeX, but that kind of ruins the whole purpose of Sweave. How can I achieve this within barplot() (or with par() or some other elegant solution)?
Sweave has chunk options width and height for the dimensions of the images. It won't control how big the plot is in the final rendered PDF as that is something LaTeX controls, but it does control the creation of the figures themselves.
From the Sweave Manual [pdf]:
Attention: One thing that gets easily confused are the width/height parameters of the R
graphics devices and the corresponding arguments to the LaTeX \includegraphics command.
The Sweave options width and height are passed to the R graphics devices, and hence affect
the default size of the produced EPS and PDF files. They do not affect the size of figures in the document, by default they will always be 80% of the current text width. Use \setkeys{Gin} to modify figure sizes or use explicit \includegraphics commands in combination with Sweave option include=FALSE.
Also read
require("utils")
?RweaveLatex
which also has details.
For your quoted example, width and height are both 6, the default. So you could do something like
<<fig=TRUE, width=8, height=5>>=
barplot(prop.table(table(x, y), margin = 2) * 100,
border = FALSE, xlab = '', ylab = '', las = 2)
#
To get the desired proportions.
[Please don't use F and T - you are asking for trouble!]
However, do note what the Manual or ?RweaveLatex say. Once in LaTeX by default the image will be included with a width equal to 0.8\textwidth. Hence you might also wish to set the width for each chunk explicitly to the size of the figure created, e.g.
\setkeys{Gin}{width=8in}
<<fig=TRUE, width=8, height=5>>=
barplot(prop.table(table(x, y), margin = 2) * 100,
border = FALSE, xlab = '', ylab = '', las = 2)
#
%% reset if you want
\setkeys{Gin}{width=0.8\textwidth}
So you have to manage the two settings:
The sweave chunk options width and height control creation of the EPS or PDF file (or both)
\setkeys{Gin} controls the width of the included figure when processed using LaTeX.
I'm trying to make colorbars, as well as raster maps, in R, and the output figures give unsightly lines in them when exported to pdf.
Here is code to generate a colorbar. It looks fine when you run it in R:
color.bar <- function(lut, min, max=-min, nticks=11, ticks=seq(min, max, len=nticks), title='') {
scale = (length(lut)-1)/(max-min)
plot(c(0,10), c(min,max), type='n', bty='n', xaxt='n', xlab='', yaxt='n', ylab='', main=title)
axis(4, ticks, las=1)
for (i in 1:(length(lut)-1)) {
y = (i-1)/scale + min
rect(0,y,10,y+1/scale, col=lut[i], border=NA)
}
}
par(mfrow=c(2,1))
par(mar=c(3,0,3,2.5))
pal = colorRampPalette(c("red","yellow"))
neg = pal(100)
pal = colorRampPalette(c("yellow","darkgreen"))
pos = pal(50)
color.bar(c(neg,pos),min=-75,max=50,ticks=c(-75,-50,-25,0,25,50))
color.bar(colorRampPalette(c("goldenrod","blue"))(25),min=0,max=1)
par(mar=c(5.1,4.1,4.1,2.1))
dev.copy2pdf(file = "colorbar_wood.pdf", height = 8, width = 1)
pdf("colorbar_wood.pdf",width=1,height=8)
par(mfrow=c(2,1))
par(mar=c(3,0,3,2.5))
pal = colorRampPalette(c("red","yellow"))
neg = pal(100)
pal = colorRampPalette(c("yellow","darkgreen"))
pos = pal(50)
color.bar(c(neg,pos),min=-75,max=50,ticks=c(-75,-50,-25,0,25,50))
color.bar(colorRampPalette(c("goldenrod","blue"))(25),min=0,max=1)
par(mar=c(5.1,4.1,4.1,2.1))
dev.off()
And here is what I get out as a pdf:
link
I need to get this up to publication quality. Any ideas on how to fix?
This is invariably an issue with the software used to render the PDF, not with R, and arises because of features such as anti-aliasing and other rendering operations that the PDF Viewer does in order to display the PDF.
This is discussed in ?pdf, notably
Note:
If you see problems with PDF output, do remember that the problem
is much more likely to be in your viewer than in R. Try another
viewer if possible. Symptoms for which the viewer has been at
fault are apparent grids on image plots (turn off graphics
anti-aliasing in your viewer if you can) and missing or incorrect
glyphs in text (viewers silently doing font substitution).
Unfortunately the default viewers on most Linux and Mac OS X
systems have these problems, and no obvious way to turn off
graphics anti-aliasing.
....
I just viewed your PDF in two different PDF viewers on Linux (Evince and Okular) and the degree to which these artefacts affected the file was different across the two viewers, with Okular giving fewer artefacts on the red-green one and none on the blue-yellow one. As such this seems to be an issue with viewing the PDF and not something with R. Your figure should therefore be publication quality.
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