15

I am trying to save an R plot as an EPS file but I have a problem with the following component of the plot - the gray transparent polygon (transparent black = gray effect):

polygon(x.polygon, y.polygon.6, col="#00000022", border=NA)

This line of code works fine when saving the plot as PDF but not as EPS. Looks like EPS does not support transparency? What other choice would I have?

Here is the code for the full plot:

postscript(file="Figure.eps", width=5.5, height=5.5, onefile=F, horizontal=F)

ts(t(data.frame(initial_timepoint, second_timepoint, third_timepoint, final_timepoint)))->obj
obj[,-c(3,7)]->obj1
plot(obj1, plot.type="single", lwd=0.6, xaxs="i",yaxs="i",xlab="",ylab="LV ejection fraction (%)",xaxt='n',yaxt='n',ylim=c(0,70),col="black")
axis(1, at=c(1,2,3,4), labels=c("1","2","3","4"),cex.axis=1)
axis(2, at=seq(0,70,10), labels=c("0%","10%","20%","30%","40%","50%","60%","70%"),cex.axis=1, las=1)
abline(v=c(2,3),lwd=0.6,lty=2)

stderr <- function(x) sqrt(var(x,na.rm=TRUE)/length(na.omit(x)))
avg<-c(mean(initial_timepoint,na.rm=T), mean(second_timepoint,na.rm=T), mean(third_timepoint,na.rm=T), mean(final_timepoint,na.rm=T))
err<-c(stderr(initial_timepoint), stderr(second_timepoint), stderr(third_timepoint), stderr(final_timepoint))

my.count <- c(1,2,3,4)
my.count.rev <- c(4,3,2,1)
y.polygon.6 <- c((avg+err*1.96)[my.count],(avg-err*1.96)[my.count.rev])
x.polygon <- c(my.count, my.count.rev)
polygon(x.polygon, y.polygon.6, col="#00000022", border=NA)
lines(avg,col="black",lwd=0.8,lty=3)
lines((avg+err*1.96),lwd=0.8,lty=3)
lines((avg-err*1.96),lwd=0.8,lty=3)

dev.off()
Kurt Pfeifle
  • 86,724
  • 23
  • 248
  • 345
Oposum
  • 1,155
  • 3
  • 22
  • 38
  • EPS does indeed not support transparency. We would need a little more context to suggest sensible alternatives. If you just want to mimic the color associated with transparent black over a white background that wouldn't be so hard, but if you have different objects behind it it's going to be hard. – Ben Bolker Mar 28 '15 at 19:49
  • 3
    The PostScript language does not support transparency, except for minor things like image masks (and masked images) and overprinting. If you need it as PostScript (or EPS) then you will have to render it to an image. – KenS Mar 28 '15 at 20:02
  • Essentially what I have is a time series of trends, 8 curves, and then superimposed confidence band "area" represented by the polygon. – Oposum Mar 28 '15 at 21:13
  • The full code is in edited version of my question above – Oposum Mar 28 '15 at 21:22
  • this is still not reproducible. You can probably get what you want by plotting the confidence band in gray (not transparent, but looking as it would) and then re-plotting anything that's been obscured by it ... – Ben Bolker Mar 28 '15 at 21:26
  • 1
    It might be possible using a non-standard extension. Ghostscript has a non-standard operator to set the rasterop which would let you do some limited amount of blending paints. Of course, being non-standard it will not be available on all interpreters and so it restricts your portability. And for your workflow, it seems this would also require you to modify the postscript generator or post-process the output somehow; not impossible, but getting more complicated with further thought. – luser droog Mar 28 '15 at 21:29
  • I was thinking, can the plot code be altered so that the polygon is drawn first, with the time series lines then superimposed on top of polygon? – Oposum Mar 29 '15 at 20:04
  • Added a solution below - guess that one should be flagged as the correct answer, as it does most closely what you were asking for! – Tom Wenseleers Apr 04 '17 at 10:40

4 Answers4

19

Although the EPS format does not natively support semi-transparency, it is still possible to use cairo_ps(), that one automatically rasterizes semi-transparent areas, and the resolution at which it does this can be controlled with the argument fallback_resolution :

cairo_ps(file = "test.eps", onefile = FALSE, fallback_resolution = 600)
qplot(Sepal.Length, Petal.Length, data = iris, color = Species, size = Petal.Width, alpha = I(0.7))
dev.off()

All the non-semi-transparent areas then nicely stay as vector graphics.

Or even shorter you can also use :

ggsave("filename.eps", device=cairo_ps, fallback_resolution = 600)

Or use the functions to export to eps using the new export package, which just came out on CRAN :

install.packages("export")
library(export)
graph2eps("filename.eps", fallback_resolution = 600)

That package also supports a number of other export formats, including Powerpoint (graph2ppt), see ?graph2vector, which also retains semi-transparency...

Tom Wenseleers
  • 7,535
  • 7
  • 63
  • 103
10

The PostScript graphics model itself does not support general transparency of page elements at all. (Hence it is also not possible for EPS.) PostScript colors are all fully opaque.

An object drawn on top of another object would overwrite and cover all lower objects with its own color leaving no room for transparent effects. (If you see something that looks like transparency overlays in a PostScript viewer or printout, then that was only emulated transparency, by flattening the two (or more) respective objects into one single rasterized area creating the illusion of transparency.)

The PDF graphics model is based on PostScript's, but it extends it in various aspects, adding several new features. One of these is real transparency for complete objects.

After Adobe added transparency to PDF, it also created an extension [1] to the existing PostScript language that was able to include code in PS programs which would add transparency to PDFs created from this PostScript via Distiller. However, when rendering on screen or printing on paper this same original PostScript including this same code, that additional transparency would not appear, and the top (transparent in PDF) object would still overwrite the bottom ones when directly used in PostScript.

What other choice would I have?

Various:

  1. Use PDF only. Don't use EPS.

  2. If you must use EPS, use a two-step process:

    • Create the PDF first.
    • Then convert from the (transparency-enabled) PDF to EPS, 'flattening' the transparent elements into rasterized areas which emulate the desired transparency effect.

[1] The name of this extension is called pdfmark. With the help of the pdfmark operator one can also add other features to PostScript code which only materialize when distilling this PostScript to PDF: annotations, interactive form fields and buttons, metadata, hyperlinks, and more. All these elements would not have any effect in the direct PostScript rendering on screen or on paper prints.

Kurt Pfeifle
  • 86,724
  • 23
  • 248
  • 345
  • 2
    The scientific journals require graphics in EPS, not PDF. Hence the need for transparent EPS. Now, if EPS is a conversion from PDF using pdfmark, would the transparency be preserved when the final version of the article PDF is created? – Oposum Mar 29 '15 at 20:01
  • @Oposum: *"...hence the need for transparent EPS"*. This doesn't follow, it is not logical. Also, there is no scientific journal in the world which can ask for "transparent EPS", since transparency simply is impossible in EPS. Never was! Your only option is "emulated" transparency, created by *flattening* (=rasterizing) from a PDF with transparency. – Kurt Pfeifle Mar 29 '15 at 20:26
  • 1
    @Oposum: Since you stated that your original plot saved as PDF *does* indeed contain transparency as you want it, just do what I said in my answer's last part -- use that two stepped process: ***(1)*** create PDF with transparency; ***(2)*** convert that PDF to EPS (transparency parts will almost *look* the PDF looks, emulating the shine-through effect via a static raster area). – Kurt Pfeifle Mar 29 '15 at 20:31
  • 1
    @Oposum: *"...if EPS is a conversion from PDF using pdfmark"*. -- You didn't get it. The `pdfmark` operator has to be used in EPS code in order to let Distiller create transparent sections in a PDF which uses that EPS code as input. You are not guaranteed to get the `pdfmark` operator back when you convert the transparency-enabled PDF back to EPS again... – Kurt Pfeifle Mar 29 '15 at 20:34
  • 2
    I did not mean that scientific journals ask for transparent EPS, they just ask for EPS and I need the transparency. – Oposum Mar 30 '15 at 22:23
  • 2
    @Oposum: You may need it but it is not ***possible*** with EPS. You have to ***fake*** it by flattening transparency-enabled PDF into EPS. – Kurt Pfeifle Mar 30 '15 at 22:26
  • In R you can also use cairo_ps(), that one automatically rasterizes semi-transparent areas - see my answer below! Quality is not perfect though - works better to export to PDF and from there to save as EPS in the full Adobe Acrobat version... – Tom Wenseleers Jul 13 '15 at 11:56
0

Instead of making gray out of transparent black, I recommend using the gray.colors() function in R to generate the shades of gray you need. Then you get the look you want in your .eps file without a problem.

-1

This is working fine for me to save .eps files

import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.use('PS')

legend = plt.legend(loc="upper left", edgecolor="black")
legend.get_frame().set_alpha(None)
legend.get_frame().set_facecolor((0, 0, 0, 0))
plt.show()
plt.savefig('fig1.eps', format='eps')
Ani
  • 1
  • 2
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 21 '23 at 04:18