12

When exporting rather complicated plots (especially ListDensityPlot) as a PDF or EPS (for publication, for example), the resulting file size can be quite large. For example:

data = Flatten[Table[{f0, f, Exp[-(f - f0)^2/25^2]}, {f0, 500, 700, 5}, {f, 300, 
 900}], 1];
plot=ListDensityPlot[data,PlotRange->{Automatic,Automatic,{0,1}},InterpolationOrder->0]

Mathematica graphics

This example data set is on the order of the size I typically work with. When I export using Export["C:\\test.pdf", plot], it generates a PDF file 23.9MB in size. If I instead try Export["C:\\test1.pdf", Rasterize[plot]] it is far smaller, but the integrity and rescalability of the image naturally suffers.

This is complicated further if my actual figure is a combined plot, such as (Edit: f goes to 900)

plot2 = Show[plot, Plot[x, {x, 500, 900}, PlotStyle -> Thick]]

Mathematica graphics

(or with some usage of Epilog) where I'd love to have the background ListDensityPlot be rasterized, but keep the other markup and plots in ``vector'' form. Or at the very least, the frame labels be non-rasterized.

Is there any way to do this?

Or, to accomplish the same goal via some other clever method?


Update

I've checked out the related question, but that's gotta be way more complicated than it needs to be (essentially exporting then importing). I've been able to utilize some of the tricks in that question to extract the plot separately from the axes:

axes = Graphics[{}, Options[plot2]]

Mathematica graphics

plots = Graphics[plot2[[1]]]

Mathematica graphics

But, the plots term loses the AspectRatio and PlotRange, etc. plots can be hit with a Rasterize, but it needs dimensional fixing.

And then, how to combine them together?

Eli Lansey
  • 1,130
  • 2
  • 15
  • 28
  • 1
    Related question: http://stackoverflow.com/q/6301676/615464 – Sjoerd C. de Vries Jan 03 '12 at 19:53
  • Thanks for that link. Looks like I might be able to work with that. What's the appropriate way to "cancel" a question? – Eli Lansey Jan 03 '12 at 20:00
  • We can close a question if there are five 'close' votes, but this is usually done only when the question is very similar to an earlier question. The closed question then serves as a pointer to the earlier question. I have to compare both questions more closely to see whether they are duplicates. It's perhaps best to don't do anything right now. – Sjoerd C. de Vries Jan 03 '12 at 20:05
  • OK, it's not exactly the same. But I may be able to use some of the tricks there. – Eli Lansey Jan 03 '12 at 20:34
  • As an active member of the Mathematica tag, have you considered committing to the [area51.se] [Mathematica proposal](http://area51.stackexchange.com/proposals/37304/mathematica?referrer=DamSFi3dv5QIDM_9uBjtlA2)? We could use your help. – rcollyer Jan 08 '12 at 15:22

4 Answers4

6

This is exactly the kind of problem for which I wrote the function linked here: http://pages.uoregon.edu/noeckel/computernotes/Mathematica/listContourDensityPlot.html

It's based on the same idea as in Heike's answer -- I just added some more features so that you can safely change the aspect ratio, opacity, and combine with other plots. See my comment in Heike's answer.

To try it with your data, do something like this:

plot = Show[
 listContourDensityPlot[data, 
  PlotRange -> {Automatic, Automatic, {0, 1}}, 
  InterpolationOrder -> 0, Contours -> None], 
 Graphics[Line[{{500, 500}, {700, 700}}]]]

There are a couple of similar functions linked from the parent page, too.

Jens
  • 426
  • 5
  • 12
  • Wow! This is pretty much exactly what I'm looking for. I can basically convert all my `ListDensityPlot`s to `listContourDensityPlot` with the switch `Contours -> None`. Thanks so much! – Eli Lansey Jan 04 '12 at 14:21
  • I am curious regarding the usage of `AbsoluteOptions[p]` vs `Options[p]`, the latter of which works better for a wacky `FrameTicks` specification. – Eli Lansey Jan 04 '12 at 15:03
  • I think I could use FullOptions, but not just Options, because I wanted to avoid getting symbolic vales like Automatic, All etc. They wouldn't work in the subsequent calculations. Maybe your problem with ticks can be solved by specifying PlotRangePadding (which I set to zero by default because I like it better). If you want to restore the usual behavior of adding 4% padding, just add the following just before the options in the Show statement, immediately before Evaluate@Apply[Sequence, frameOptions]: PlotRangePadding -> If[FreeQ[{opts}, PlotRange], .04 {-1, 1}.rangeCoords, 0] – Jens Jan 04 '12 at 17:28
  • After some poking around, it seems that `AbsoluteOptions` and `Options` have inconsistencies, especially if the user (i.e. me) specifies particular values for `FrameTicks`. Then it needs to use `Options` to get the correct values, and `AbsoluteOptions` throws an error. – Eli Lansey Jan 04 '12 at 19:05
  • Ah, I see. Hopefully it will work if you change the variables densityOptions and contourOptions by replacing "Except[{Prolog, Epilog,... " with "Except[{Prolog, Epilog, FrameTicks,... " I thought FrameTicks cannot cause problems when I already specified Frame->None but that may not be correct. If this doesn't fix it, could you give a small example with your tick function? – Jens Jan 04 '12 at 20:16
  • Looking at the FrameTicks handling, I think I found a bug in Mathematica. The following is a valid FrameTicks option, but AbsoluteOptions throws an error with it: Define p = Plot[Sin[x], {x, 0, \\[Pi]}, Frame -> True, FrameTicks -> {{{{1, 1}}, {{1, 1}}}, {{{1, 1}}, {{1, 1}}}}] and then ask for FrameTicks /. AbsoluteOptions[p] which leads to a message that looks like the option was improperly fed into Ticks. – Jens Jan 05 '12 at 01:35
  • 2
    `AbsoluteOptions` has scores of faults currently that tech support acknowledge as bugs. – Mike Honeychurch Jan 05 '12 at 07:09
  • There seems to be 3 classes of errors with `AbsoluteOptions`. 1) when it doesn't recognize an option for a function; 2) it does recognize the option but returns an error or incorrect value; 3) the option is recognized but the setting of another option somehow causes a failure. As an example of #3 the setting for `Joined` messes up retrieving `PlotRange` for `DateListPlot`. `True` allows a result to be returned. `False` causes a breakage. There are numerous examples like this that show `AbsoluteOptions` to be a real hit and miss function at the moment. – Mike Honeychurch Jan 05 '12 at 23:32
  • Scary. I reported my issue to Wolfram and got a reply that didn't really address the issue, telling me I should instead use FrameTicks -> {{{1, 1}}, {{1, 1}}}. So I followed up and am currently waiting for a reply... – Jens Jan 06 '12 at 02:49
  • 2
    Yeah it is something that needs a total revamp for V9. – Mike Honeychurch Jan 06 '12 at 03:21
  • Just for completeness: tech support have now acknowledged it is a bug. – Jens Jan 16 '12 at 17:24
5

If you're dealing with 2D plots, you could combine a rasterized plot with vectorized axes by using Inset. For example

plot2 = ListDensityPlot[data, 
   PlotRange -> {Automatic, Automatic, {0, 1}}, 
   InterpolationOrder -> 0, Axes -> False, Frame -> False, 
   PlotRangePadding -> 0];

plotRange = PlotRange /. AbsoluteOptions[plot2, PlotRange];

plot = Graphics[{
  Inset[Image[plot2], plotRange[[All, 1]], {Left, Bottom}, Scaled[{.96, .96}]],
  Line[{{500, 500}, {700, 700}}]}, 
 Frame -> True, AspectRatio -> 1, 
 PlotRange -> plotRange, PlotRangePadding -> Scaled[.02]]

Export["test.pdf", plot]

produces a .pdf of about 400 KB. The frame, tick marks, and black line are still vectorized, so they stay sharp when zooming in:

detail of image

Heike
  • 24,102
  • 2
  • 31
  • 45
  • I personally also favor this general approach. One just has to be careful with the Scaled coordinates. Try this with your plot to see what I mean: Show[plot, Graphics[{EdgeForm[Red], FaceForm[], Rectangle[{0, 0}, {1000, 1000}]}], PlotRange -> All] – Jens Jan 04 '12 at 07:13
  • @noeckel I agree that using `Inset` in this way is rather fragile; even changing the aspect ratio breaks it. Ideally I would like to do something like `plot = Graphics[{Texture[plot2], Polygon[Tuples[plotRange][[{1, 2, 4, 3}]], VertexTextureCoordinates -> Tuples[{0, 1}, 2][[{1, 2, 4, 3}]]]}, Frame -> True]` but for some reason, Mathematica refuses to export the resulting plot to pdf (at least in my version of Mathematica). – Heike Jan 04 '12 at 13:54
  • I like this approach, but I think @noeckel wrote an excellent function. – Eli Lansey Jan 04 '12 at 14:22
  • @heike I tried the same thing with the same result. My recollection is that I attributed it to a bug in vertex color PDF export, but I didn't pursue it further. – Jens Jan 04 '12 at 18:07
0

If you are exporting as PDF, EPs or WMF, then the text should remain as vectors even if you have a rasterized component to the graphics.

I think the trick is to set the number of plot points to some low number in the ListDensityPlot command and then export as PDF as normal.

Verbeia
  • 4,400
  • 2
  • 23
  • 44
  • My hope is to generate a rasterized plot, with non-rasterized text, and export that. Even adjusting `MaxPlotPoints`, that might not help for some more complicated graphs which require lots of points. – Eli Lansey Jan 03 '12 at 21:34
  • Also, using `MaxPlotPoints->2` which is the smallest possible option, doesn't change the exported file size. – Eli Lansey Jan 03 '12 at 21:40
0

How about just plotting the function rather than making a list?

plot=DensityPlot[Exp[-(f - f0)^2/25^2], {f0, 500, 700}, {f, 300, 900}, 
 Epilog -> {Thick, Line[{{500, 500}, {700, 700}}]}, PlotPoints -> 50]

Export["test.pdf", plot]

file size 1.1MB

Mike Honeychurch
  • 1,683
  • 10
  • 17
  • This was a sample data set. In practice I'm working with the output from many computer simulations. – Eli Lansey Jan 03 '12 at 23:30
  • And the function plotted is far more complicated than a straight line. – Eli Lansey Jan 03 '12 at 23:42
  • @Eli Lansey can you update with information about the real life data, is it 3D or do you transform it to 3D etc. etc. Maybe provide a sample. So you want to overlay the plot of function onto the density plot of your list? There is Show, Overlay and Inset (as per Heike's example). – Mike Honeychurch Jan 04 '12 at 00:10
  • The `data` in the problem is an artificially constructed, simple, but decent representative of the type of, format of, and size of data I typically work with. I then compare the data set with theoretical models, which I overlay on the graph. My goal is to get a smaller exported file for inclusion in publications. – Eli Lansey Jan 04 '12 at 14:00