Skip to main content

plotting - How can I get Mathematica to not mis-align plot labels when exporting to pdf without rasterizing the text?


I have this code:


p = ListPlot[Table[Table[{x, m x}, {x, 0, 20000, 100}],
{m, 0.05/20000, 7/20000, (7 - 0.05)/20000/20}],
PlotLabels -> {"a", "asdfdfasfasdfasd", a, a, a, a, a, a, a, a,
"adfsfasda", "aasdfadfsfasdafsdfasd"},
PlotRange -> {Full, {0, 2}}, ImageSize -> 500]

rp = Rasterize[p]
Export["/tmp/foo2-p.pdf", p]
Export["/tmp/foo2-rp.pdf", rp]
Export["/tmp/foo2-p.png", p]
Export["/tmp/foo2-rp.png", rp]

I get the following images:


foo2-p.pdf:


foo2-p.pdf


foo2-rp.pdf:



foo2-rp.pdf


foo2-p.png:


foo2-p.png


foo2-rp.png:


foo2-rp.png


If I rasterize first, or if I export to png, then the long names are horizontally aligned with the other names. However, if I export directly to pdf, then the names are horribly misaligned. How do I fix this issue without rasterizing the labels? And why is Mathematica doing this? (If it's relevant, I'm using Mathematica 11.2.0.0 on Linux x86_64.)




I've noticed that, using ImageMagick to convert the pdfs to pngs to upload them, the plot labels seem to be centered in boxes that are correctly aligned. So I suspect that one way of fixing this could be somehow tricking Mathematica into thinking that the shorter text is longer than it (a la LaTeX's \smash, \rlap, \llap, \phantom, etc).



Answer



I'm coming the the conclusion that pdf export is buggy in computing bounding boxes. I discovered I can fix the offset by adding:



/. Text[v_, Offset[{dx_, dy_}, {x_, y_}], {0, 0}] :>
Text[v, Offset[{14, 0}, {x, y}], {Left, Center}]

(14 is a magic number that comes from inspecting the input form of graphics and looking that the difference between the size of the image as given by Dimensions of the results of Text[] within Graphics[] and the specified dx offset)


So this code seems to work:


p = ListPlot[Table[Table[{x, m x}, {x, 0, 20000, 100}],
{m, 0.05/20000, 7/20000, (7 - 0.05)/20000/20}],
PlotLabels -> {"a", "asdfdfasfasdfasd", a, a, a, a, a, a, a, a,
"adfsfasda", "aasdfadfsfasdafsdfasd"},
PlotRange -> {Full, {0, 2}}, ImageSize -> 500] /.

Text[v_, Offset[{dx_, dy_}, {x_, y_}], {0, 0}] :>
Text[v, Offset[{14, 0}, {x, y}], {Left, Center}]

Addendum: From https://mathematica.stackexchange.com/a/163490/12258, another option which seems to help but not fully solve the problem (see also How does pdf export handle text alignment?) is to include an explicit FontSize:


p = ListPlot[Table[Table[{x, m x}, {x, 0, 20000, 100}],
{m, 0.05/20000, 7/20000, (7 - 0.05)/20000/20}],
PlotLabels -> Map[Style[#1, 10]&,
{"a", "asdfdfasfasdfasd", a, a, a, a, a, a, a, a,
"adfsfasda", "aasdfadfsfasdafsdfasd"}],
PlotRange -> {Full, {0, 2}}, ImageSize -> 500]

Comments

Popular posts from this blog

plotting - Filling between two spheres in SphericalPlot3D

Manipulate[ SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, Mesh -> None, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], {n, 0, 1}] I cant' seem to be able to make a filling between two spheres. I've already tried the obvious Filling -> {1 -> {2}} but Mathematica doesn't seem to like that option. Is there any easy way around this or ... Answer There is no built-in filling in SphericalPlot3D . One option is to use ParametricPlot3D to draw the surfaces between the two shells: Manipulate[ Show[SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], ParametricPlot3D[{ r {Sin[t] Cos[1.5 Pi], Sin[t] Sin[1.5 Pi], Cos[t]}, r {Sin[t] Cos[0 Pi], Sin[t] Sin[0 Pi], Cos[t]}}, {r, 1, 2 - n}, {t, 0, Pi}, PlotStyle -> Yellow, Mesh -> {2, 15}]], {n, 0, 1}]

plotting - Plot 4D data with color as 4th dimension

I have a list of 4D data (x position, y position, amplitude, wavelength). I want to plot x, y, and amplitude on a 3D plot and have the color of the points correspond to the wavelength. I have seen many examples using functions to define color but my wavelength cannot be expressed by an analytic function. Is there a simple way to do this? Answer Here a another possible way to visualize 4D data: data = Flatten[Table[{x, y, x^2 + y^2, Sin[x - y]}, {x, -Pi, Pi,Pi/10}, {y,-Pi,Pi, Pi/10}], 1]; You can use the function Point along with VertexColors . Now the points are places using the first three elements and the color is determined by the fourth. In this case I used Hue, but you can use whatever you prefer. Graphics3D[ Point[data[[All, 1 ;; 3]], VertexColors -> Hue /@ data[[All, 4]]], Axes -> True, BoxRatios -> {1, 1, 1/GoldenRatio}]

plotting - Adding a thick curve to a regionplot

Suppose we have the following simple RegionPlot: f[x_] := 1 - x^2 g[x_] := 1 - 0.5 x^2 RegionPlot[{y < f[x], f[x] < y < g[x], y > g[x]}, {x, 0, 2}, {y, 0, 2}] Now I'm trying to change the curve defined by $y=g[x]$ into a thick black curve, while leaving all other boundaries in the plot unchanged. I've tried adding the region $y=g[x]$ and playing with the plotstyle, which didn't work, and I've tried BoundaryStyle, which changed all the boundaries in the plot. Now I'm kinda out of ideas... Any help would be appreciated! Answer With f[x_] := 1 - x^2 g[x_] := 1 - 0.5 x^2 You can use Epilog to add the thick line: RegionPlot[{y < f[x], f[x] < y < g[x], y > g[x]}, {x, 0, 2}, {y, 0, 2}, PlotPoints -> 50, Epilog -> (Plot[g[x], {x, 0, 2}, PlotStyle -> {Black, Thick}][[1]]), PlotStyle -> {Directive[Yellow, Opacity[0.4]], Directive[Pink, Opacity[0.4]],