11

I have a data file which can be downloaded from here.

In order to plot this, I use the following Mathematica code

SetDirectory[" ... "];
data = Import["pss_data.dat", "Table"];
S0 = ListPlot[data, Axes -> False, Frame -> True, 
FrameLabel -> {"x", OverDot["x"]}, RotateLabel -> False, 
FrameStyle -> Directive[FontSize -> 17, FontFamily -> "Helvetica"], 
PlotStyle -> {Black, PointSize[0.001]}, 
PlotRange -> {{-10.1, 11}, {-45, 45}}, ImageSize -> 550]
Export["pss_plot.eps", S0, "EPS"];

However, the quality of the plot is not satisfactory. Let me be more specific. I realized, that the element which causes the problem is indeed the PointSize option. Here is a magnification of the .eps output created using Mathematica

enter image description here

OK, this is a decent plot, but take a look at this one created using gnuplot

enter image description here

Now, the problem it is far from obvious. The dots which represent the points are way too big in the Mathematica plot. I tried to reduce the PointSize of them, but it seems that it cannot be smaller 0.001. You may insert 0.0001 but these is no effect. I even tried to Rasterize the plot before export it to .eps but again I could not achieve the desired quality.

So, my question: Is it possible to achieve the same plot using Mathematica? Well, it should be. In fact, the question can be rephrased as: How could we shrink more the PointSize in ListPlot?

Many thanks in advance.

EDIT:

Following Jens's method the output .eps file is the following:

enter image description here

Obviously, almost the entire right part of the plot is missing. Only if I set Magnification -> 1 I can obtain all the plot. But then, zooming in you can see that the dots are still big enough as in my initial output. So, back to square one!

Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263
Vaggelis_Z
  • 8,740
  • 6
  • 34
  • 79
  • How about changing PlotStyle -> Directive[Gray, PointSize[0.001], Opacity[0.5]] ? – b.gates.you.know.what Feb 04 '13 at 10:14
  • @b.gatessucks The same output as before. Only now the dots are with gray color. Their size has not been reduced. – Vaggelis_Z Feb 04 '13 at 10:23
  • Βαγγέλη, I have had a go and I can export the whole plot with ImageSize->1000 onto eps. Also, there is a potentially related question with adaptive point size for dense plots – gpap Feb 04 '13 at 12:50
  • @gpap How did you manage to obtain the entire plot using ImageSize->1000? Anyway, are dots smaller now? If you zoom inside the plot does it look like the gnuplot output? – Vaggelis_Z Feb 04 '13 at 13:18
  • Yes, the dots seem fine in my export. But if they don't I think the question I linked to will definitely be of help – gpap Feb 04 '13 at 14:25
  • @gpap In your export about half of the plot is missing form the output .pes file! Don't you think that this is a problem?! – Vaggelis_Z Feb 04 '13 at 21:05
  • Huh?!? Osx automatically converts it to pdf and looks perfect. It's never been so different to the respective eps. I'll probably need to check against including it in a latex document-sincere apologies – gpap Feb 04 '13 at 22:29

4 Answers4

13

Strictly speaking what you observe is a bug in handling of the Point Graphics primitive by Export.

One workaround is to export to SVG format, edit it and then save as EPS. Here is a way to go (some numbers may be version-specific, I use Mathematica 9.0.1):

Export["test.svg",
  StringReplace[ExportString[S0, "SVG"], 
    "rx='0.5' ry='0.5'" -> "rx='0.2' ry='0.2'"], "String"]

The exported SVG file can be opened by Inkscape 0.48.3.1 and then saved to EPS or PDF format. Here is how exported PDF file looks in Adobe Acrobat 11:

screenshot

You can tune the size 0.2 of the circles for your taste.


EDIT

In a comment @cormullion suggets more direct approach which does not require an intermediate program:

Export["test.eps",
  StringReplace[ExportString[S0, "EPS"], {"\t" -> " ", " 1 w" -> " 0.3 w"}], "String"]

EDIT 2

Here is another, much more direct approach:

S0 = Graphics[{Disk[#, .01] & /@ data}, Axes -> False, Frame -> True, 
   FrameLabel -> {"x", OverDot["x"]}, RotateLabel -> False, 
   FrameStyle -> Directive[FontSize -> 17, FontFamily -> "Helvetica"],
    PlotRange -> {{-10.1, 11}, {-45, 45}}, ImageSize -> 550, 
   AspectRatio -> 1/GoldenRatio];
Export["pss_plot.eps", S0];

Here is how exported EPS file looks opened in Acrobat 11:

screenshot 2


EDIT 3

Here is a way to export EPS file with rasterized plot (about 900 kb in size):

S0 = Graphics[{Disk[#, Offset[.3]] & /@ data}, Axes -> False, 
   Frame -> True, FrameLabel -> {"x", OverDot["x"]}, 
   RotateLabel -> False, 
   FrameStyle -> Directive[FontSize -> 17, FontFamily -> "Helvetica"],
    PlotRange -> {{-10.1, 11}, {-45, 45}}, ImageSize -> 550, 
   AspectRatio -> 1/GoldenRatio];

Export["pss_plot.eps", 
  Rasterize[Style[S0, Antialiasing -> False], "Image", 
   ImageResolution -> 1000]];

If you need higher resolution you can increase the ImageResolution. If you want to add a preview to the EPS file, use the "PreviewFormat" option:

Export["pss_plot.eps", 
  Rasterize[Style[S0, Antialiasing -> False], "Image", 
   ImageResolution -> 1000], "PreviewFormat" -> "TIFF"];

Note that rasterization with high resolution requires a lot of memory and Mathematica cannot use more than approximately 1.2 Gb of memory under 32 bit systems. The memory requirements can be reduced by incremental rendering (see the "EDIT 4" section below).

Here is how exported plot looks in Adobe Acrobat (I switched off downsampling for bitmap images in Acrobat's EPS → PDF conversion settings):

screenshot 3


EDIT 4

For completeness, here I present an incremental rendering technique which allows substantially reduce the memory requirements when rendering Mathematica's graphics with high resolution. It works both for Graphics and Graphics3D. Note that for the current task I convert the image to grayscale for saving memory, generally it is not necessary.

One can also note the loose of FrameLabel - it is due to a bug in FullGraphics, the latter is used for avoiding a bug in ImageResolution which causes diminished FrameTicks. These bugs are not critical for this application: instead of FullGraphics one can use the CustomTicks package which "fixes" all these bugs.

S0 = Show[
   FullGraphics[
     Graphics[{}, Axes -> False, Frame -> True, 
      PlotRange -> {{-10.1, 11}, {-45, 45}}, 
      AspectRatio -> 1/GoldenRatio]] /. 
    AbsoluteThickness[_] -> Thickness[Medium], 
   AspectRatio -> 1/GoldenRatio, 
   Epilog -> {Disk[#, Scaled[.0004 {1, GoldenRatio}]] & /@ data}, 
   BaseStyle -> {FontSize -> Scaled[.02], FontFamily -> "Helvetica"}, 
   ImageSize -> {360, Round[360/GoldenRatio]}, 
   ImagePadding -> {{Scaled[.04], Scaled[.01]}, {Scaled[.04], 
      Scaled[.01]}}];
p = Graphics[Inset[S0, {0, 0}, Center, {1, 1}], 
  PlotRangePadding -> None, ImagePadding -> None, ImageMargins -> 0, 
  PlotRange -> {{-1/2, 1/2}, {-1/2, 1/2}}]

divisions = 4;
bins = Partition[FindDivisions[{-1/2, 1/2}, divisions], 2, 1];
plotRanges = Table[{x, y}, {y, Reverse@bins}, {x, bins}];
fileNames = 
  Table[FileNameJoin[{$TemporaryDirectory, 
     "temp part " <> ToString[i] <> ".mx"}], {i, 1, 
    Length[Flatten[plotRanges, 1]]}];

Do[Print@Export[fileNames[[i]], 
   ColorConvert[
    Rasterize[Show[p, PlotRange -> Flatten[plotRanges, 1][[i]]], 
     "Image", ImageResolution -> 400], "Grayscale"]], {i, 1, 
  Length[Flatten[plotRanges, 1]]}]

(*ImageTake drops last line of white pixels: it is a bugfix*)
Export["Graphics.eps", 
 ImageAssemble[
  Partition[
   Table[ImageTake[Import[file], {1, -2}], {file, fileNames}], 
   divisions]]];

FileByteCount["Graphics.eps"]

DeleteFile /@ fileNames;
1653237

We have generated a 8000x8000 image and exported it to EPS. Here is how it looks in Acrobat:

screenshot 3

Alexey Popkov
  • 61,809
  • 7
  • 149
  • 368
  • Unfortunately, I cannot reproduce your pdf output. It creates a huge .svg file (about 7MB) and then when I import it into Inkscape I loose the Fonts and the special characters (like the OverDot in the y label). Also when I export it as .eps I choose 1000 dpi resolution but again the image is not the desired ... – Vaggelis_Z Feb 04 '13 at 13:10
  • @Vaggelis_Z I also loose the OverDot when exporting to "SVG" and the font becomes Arial. But the problem was not the font: it is easy to add axes labels in Inkscape (or even Acrobat Pro 11). I give a solution to control point's size. – Alexey Popkov Feb 04 '13 at 13:42
  • Yes, indeed the fonts was not the problem. However, the exported .eps file form Inkscape (or GIPM) is about 20MB size! And then, you have to make extra modifications regarding the fonts. I want to believe that there must be another more direct for solving to my problem. Your solution requires an intermediate program. I refuse to believe that something so easy in gnuplot, requires too much effort in Mathematica. – Vaggelis_Z Feb 04 '13 at 14:01
  • 2
    @AlexeyPopkov That's a brilliant trick - never seen it before. For EPS, you can do: StringReplace[ ExportString[S0, "EPS"], {" " -> " ", " 1 w" -> " 0.3 w"}] >> "test.eps" to lower the line weight (where the first string is a tab, which gets translated to RawTab...) – cormullion Feb 04 '13 at 17:05
  • @cormullion Thanks! This works perfect: SetOptions[OpenWrite, PageWidth -> Infinity, FormatType -> OutputForm]; StringReplace[ ExportString[S0, "EPS"], {"\t" -> " ", " 1 w" -> " 0.3 w"}] >> "test.eps". – Alexey Popkov Feb 04 '13 at 17:31
  • @AlexeyPopkov Your revised method is working fine! Could you explain what exactly {Disk[#, .01] & /@ data} does? However, the exported eps file is about 30MB! The corresponding eps obtained from gnuplot is less than 1MB! – Vaggelis_Z Feb 04 '13 at 21:14
  • @AlexeyPopkov Your .eps output is exactly the same (regarding the size of the dots) with the one I obtained using gnuplot. The only problem is the exported eps from Mathematica is about 30 times bigger in size! Why this is happening since visually the quality is the same? Is there a way to reduce its size? – Vaggelis_Z Feb 04 '13 at 21:21
  • @AlexeyPopkov I have a suspicion that gnuplot does not export "true" vector drawings, where one can access to every point as to separate object, but "bitmappes" them in high resolution - therefore that output is not so "heavy". Can be done the same with Mathematica? – Vaggelis_Z Feb 04 '13 at 21:23
  • Perhaps some system dependacy? On linux export to EPS produces a real vector eps file with no preview. The file size is essentilaly unchanged if you vary ImageSize. – george2079 Feb 04 '13 at 23:26
  • @Vaggelis_Z As I understand, PostScript is not just a vector format but also a program and there may be many ways to reduce filesize by some optimizations. May be gnuplot uses some optimization tecnique. The 30 times difference is not surprising me. – Alexey Popkov Feb 05 '13 at 01:58
  • @Vaggelis_Z See "EDIT 3" section for rasterized solution. – Alexey Popkov Feb 05 '13 at 02:01
  • @george2079 See "EDIT 3" on how to add a preview. By default Mathematica does not include a preview into exported EPS file. The file size of purely vector drawing should not depend on the specified size of the drawing, nothing unexpected. – Alexey Popkov Feb 05 '13 at 02:04
  • @Vaggelis_Z See corresponding Documentation pages: "Function (&)", "Map (/@)", "Disk". – Alexey Popkov Feb 05 '13 at 02:08
  • @AlexeyPopkov For ImageResolution->1000 the kernel shuts down, even though I have 4GB of memory. I know that my OS (Win XP 32bit) cannot access more than about 3GB of memory. So, Mathematica should at least use these 3GB. I reduced Resolution to 500 and the output is decent. – Vaggelis_Z Feb 05 '13 at 08:24
  • @AlexeyPopkov By the way, I plan to upgrade my PC using Win XP 64bit with 16GB of RAM. In this 64bit OS how much RAM can Mathematica 9 access to? – Vaggelis_Z Feb 05 '13 at 08:27
  • @Vaggelis_Z Mathematica starting at least from version 5 is shipped with 64bit versions of MathKernel and FrontEnd. AFAIK it should see all your memory, even 100 Gb of RAM on 64 bit systems. – Alexey Popkov Feb 05 '13 at 10:47
4

Poincaré sections like this are terrible when you include them in a multi-page PDF document (e.g. via $\LaTeX$) as vector graphics because they slow down then scrolling and paging for the reader, to the point where it becomes unbearable. Vector graphics is simply an inefficient and inappropriate way to represent graphics that mainly consist of giant point clouds. In particular for publication purposes, you should always convert such plots to bitmap!

It's not so much the storage that't the problem, it's the fact that the PDF interpreter has to decode the points every time you come to the page that displays your plot, and that takes a lot of pointless processing for lots of points (pun intended). Just export to PNG and forget about EPS.

Or (if you use an old $\LaTeX$ version) use the following trick from this answer to create your EPS file with rasterized points:

rasterTrick[plot_] := 
Show[plot, 
 Prolog -> {Opacity[0], Texture[{{{0, 0, 0, 0}}}], 
   VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}}, 
   Polygon[{{0, 0}, {.1, 0}, {.1, .1}}]}]

Export["t.eps", Style[S0 // rasterTrick, Magnification -> 2]]
Jens
  • 97,245
  • 7
  • 213
  • 499
  • I followed the rasterTrick you described but in the exported .eps file almost half of the plot (yes indeed it is a Poincare Surface of Section - PSS) is missing! – Vaggelis_Z Feb 05 '13 at 08:20
  • It works for me. Always has. What part of the plot is cut off? Or do you mean that certain points are missing from the plot? – Jens Feb 05 '13 at 16:03
  • See my EDIT. I provide the exact .eps output in which the entire right part of the PSS is missing. – Vaggelis_Z Feb 05 '13 at 21:10
  • @Vaggelis_Z what you see is going to depend on the software you use for viewinng, which is why people are getting different results here. Some viewers auto scale to fit the page, some don't. – george2079 Feb 05 '13 at 21:24
  • @george2079 How can I rescale it in order to fit the page? I use GSview 5 to view .ps/eps files. – Vaggelis_Z Feb 05 '13 at 21:32
1

You could change your ImageSize option? 550 seems very low...

screen grab

cormullion
  • 24,243
  • 4
  • 64
  • 133
  • I can go up to about ImageSize->600. Beyond that I cannot export in .eps the entire plot. But again if I use larger ImageSize the size of the dots is still the same. – Vaggelis_Z Feb 04 '13 at 10:25
  • with this approach what you need to do is increase imagesize and add scaling code to the postscript output to scale it back down to fit the page. This will effectivly shrink everything, points, lineweights, etc. – george2079 Feb 05 '13 at 19:04
0

It seems if you specify markers then the size is not cut off at some arbitrary threshold:

 ListPlot[data,PlotMarkers->{Graphics[Disk[]],.01}]

Note this will increase your file size quite a lot since mathematica draws the filled disk using 8 bezier curves, each one hard coded (48 floats (400+ bytes) for each marker)

The default marker is drawn as a zero-length line with round end caps. I guess somebody doesn't like the arc operators.


Yet another approach, this replaces your marker with arbitrary postscript code: (no messing around with imagesize)

SetOptions[OpenWrite, PageWidth -> Infinity, FormatType -> OutputForm]
StringReplace[
      ExportString[ListPlot[data], "EPS"] , {"\t" -> " ", 
         " m 0 0 rL s\n" -> " mymarker\n", 
        "%%EndComments" -> 
        "%%EndComments\n/mymarker {dup 2 index exch moveto 1 0 360 arc fill} def\n"} ] >> test.ps

Note this is defining a procedure for the marker and so will not baloon your file size. The 1 in 1 0 360 arc is the marker radius, which can be as small as you like.

george2079
  • 38,913
  • 1
  • 43
  • 110