Skip to main content

labeling - Avoiding overcomplicated structure of groups, masks and splited text on vector format plot export


I'm trying to generate a template for exporting figures and plots in a consistent way that will allow easy editing in any vector based drawing software (such as illustrator). My problem is that exported figures in vector format have an (apparently) unnecessarily cumbersome structure. For instance


p = Plot[x, {x, 0, 1}
, Frame -> True
, FrameLabel -> {"Abscissa [unit]", "Ordinate [a.u]"}
, BaseStyle -> {FontSize -> 11, FontFamily -> "Helvetica",
FontTracking -> "Plain", TextJustification -> 0,

PrivateFontOptions -> {"OperatorSubstitution" -> False}}
]
Export["test.svg",p,"SVG"]

will generate an SVG file which code look like this:









Abscissa
[
unit
]


See how each piece of text, and tick stroke has a group, a clipping mask and the text is split in several text instances. That code also is cumbersome to manipulate when opened in Illustrator


Screenshot layers and groups seen in Illustrator


The described problem also exists in PDF and EPS formats, but is easier to see in the SVG code.



Is it possible to control this behaviour?


At least I would like to remove any clipping masks AND groups, and force all the text in a label to be a single object. Ideally I would like to have a group for traces, another for axis and another for labels


I tried making TextJustification -> 0,FontTracking -> "Plain" hoping at least the text split could be solved, but with no consequence.


Edit


Based on this question one strategy would be to parse back the SVG file (that is XML mark-up) , join all text that is in the same group. and then remove groups and clipping paths. That was not the kind of solution I was expecting, but it may work.


Any help on how to do this string or XML translation?




A
B

C


into


 ABC

Edit 2


A very preliminary and partially failed solution is to create the SVG and parse it back as XML, and take what is inside the groups (g) and clips (clipPath), and export it back as text.


p = Plot[x, {x, 0, 1}
, Frame -> True

, FrameLabel -> {"Abscissa [unit]", "Ordinate [a.u]"}
, BaseStyle -> {FontSize -> 11, FontFamily -> "Helvetica",
FontTracking -> "Plain", TextJustification -> 0,
PrivateFontOptions -> {"OperatorSubstitution" -> False}}
]

Export["test2.svg",
ExportString[
ImportString[ExportString[p, "SVG"], "XML"] /.
XMLElement["g", __, {XMLElement["clipPath", __], x_}] -> x,

"XML"], "Text"]

But the problem is that some groups have transform definitions that redefine the coordinate system and that information is currently lost. Also not all the groups are removed, i don't understand why. I would appreciate some help on this XML substitution rules and data parsing.



Answer



This is the reply from Wolfram Research Technical Support [CASE:631799]:



After consultation with a developer, there is nothing really that can be done with the Export function directly in terms of simplifying the group structure of SVG files. You may be able to develop some system by programmatically parsing the file down, but this would likely not be simple or easy.


I can say that our developers are aware that exporting to vector based formats could be improved in Mathematica. Therefore, future versions of Mathematica might see improvement in this respect. I certainly can't make any guarantees about what might make it into any specific future version of Mathematica, but I can say that our developers do know that users would like improvement in this area.



So I guess the answer to my question is that so far (M v9) there is no native way to avoid the cumbersome structure of objects generated when exporting vector graphics. Therefore the only way around is to open the poorly generated file, to then parse and re-structure it.



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 - Mathematica: 3D plot based on combined 2D graphs

I have several sigmoidal fits to 3 different datasets, with mean fit predictions plus the 95% confidence limits (not symmetrical around the mean) and the actual data. I would now like to show these different 2D plots projected in 3D as in but then using proper perspective. In the link here they give some solutions to combine the plots using isometric perspective, but I would like to use proper 3 point perspective. Any thoughts? Also any way to show the mean points per time point for each series plus or minus the standard error on the mean would be cool too, either using points+vertical bars, or using spheres plus tubes. Below are some test data and the fit function I am using. Note that I am working on a logit(proportion) scale and that the final vertical scale is Log10(percentage). (* some test data *) data = Table[Null, {i, 4}]; data[[1]] = {{1, -5.8}, {2, -5.4}, {3, -0.8}, {4, -0.2}, {5, 4.6}, {1, -6.4}, {2, -5.6}, {3, -0.7}, {4, 0.04}, {5, 1.0}, {1, -6.8}, {2, -4.7}, {3, -1.