Tweaking style/attributes of existing Graphics objects in Mathematica

ⅰ亾dé卋堺 提交于 2019-12-22 07:22:59

问题


One of Mathematica's strengths is its consistent underlying representation of objects. Thus, to change attributes of a plot without redoing the computation used to generate it, I could do something like

Replace[myplot, {Graphics[x_List, y_List] :> 
 Graphics[x,Flatten[{y, 
  BaseStyle -> {FontFamily -> Helvetica, FontSize -> 20}}]]}]

Unfortunately, every time I want to use this approach to modify a plot in order to change the style/color of lines, points, fonts, etc. I have to figure out what the appropriate replacement rule is by trial and error, which negates any efficiency gained by not having to recompute the plotted data. Here's another example:

myplot = Plot[{Cos[x], Sin[x]}, {x, 0, 2 Pi}, 
  PlotStyle -> {{Red, Dashing[None]}, {Green, Dashing[None]}}]

myplot /. { {x___, PatternSequence[Red, Dashing[_]], y___}
              -> {x, Green, Thickness[.02], Dashing[Tiny], y},
            {x___, Green, y___}
              -> {x, Thickness[Large], Red, y} }

This gets the job done (changes line color/dashing/thickness), but seems voodoo-ish.

Is there any documentation (guides or tutorials) -- short of poring over the exact specifications for Graphics objects and primitives -- that could guide me in constructing the appropriate replacements?.. If not, are there better ways of tweaking the appearance of plots without recomputing (other than saving data in a variable and using ListPlot)?


回答1:


I await more examples of your desired manipulations, but for now I'll point out that it may be possible to do a class of them without replacements at all. Forced to merely guess at what you want, one interpretation follows.

myplot = Plot[{Sin[x], Csc[x]}, {x, 1, 10}];

Replace[myplot, {Graphics[x_List, y_List] :> 
   Graphics[x, 
    Flatten[{y, 
      BaseStyle -> {FontFamily -> "Helvetica", FontSize -> 20}}]]}]

Show[myplot, BaseStyle -> {FontFamily -> "Helvetica", FontSize -> 20}]

As you can see, in this case Replace is not needed.


Addressing your updated question, there are two different categories of graphical objects in a Plot output.

  1. The plotted lines of the functions (Sin[x], Cos[x]) and their styles are "hard coded" into Line objects, which Graphics can understand.

  2. Auxiliary settings such as Axes -> True, PlotLabel -> "Sine Cosecant Plot" and AxesStyle -> Orange are understood by Graphics directly, without conversion, and therefore remain within the myplot object.

The second kind of settings can be easily changed after the fact because they are soft settings.

The first kind much be processed in some way. This is complicated by the fact that different *Plot functions output different patterns of Graphics and Plot itself may give different patterns of output depending on the input it is given.

I am not aware of any global way to restyle all plot types, and if you do such restyling often, it probably makes more sense to retain the data that is required and simply regenerate the graphic with Plot. Nevertheless, for basic uses, your method can be improved. Each function plotted creates a Line object, in the given order. Therefore, you can use something like this to completely restyle a plot:

myplot = Plot[{Cos[x], Sin[x]}, {x, 0, 2 Pi}, 
  PlotStyle -> {{Red, Dashing[None]}, {Green, Dashing[None]}}]

newstyles = Directive @@@
   {{Green, Thickness[.02], Dashing[Tiny]},
    {Thickness[Large], Red}};
i = 1;
MapAt[# /. {__, l : Line[__]} :> {newstyles[[i++]], l} &, myplot, {1, 1}]

Please note the part in bold-italic in the last line of code above. This is the part specification for the location of the Line objects within myplot, and it may change. Usually this will work as is, but if you find that you must change this often, a function to detect its position should be possible (ask if needed).


Graphics Inspector

telefunkenvf14's comment reminded me that I was negligent to not mention the Graphics Inspector.

While I personally tend to avoid extensive after-Plot restyling, because I like to keep everything on one place (the Plot command), and I prefer to make what changes I do with code, so that there is a record of my settings without having to dig into the Graphics object, the Graphics Inspector is directly applicable.

  • Double click the plot. The border should change from orange to thick gray.
  • Single click one of the plot lines. (the pointed should change when you hover over an element)
  • Press Ctrl+g to open the Graphics Inspector.
  • Make the changes you desire, and close the Graphics Inspector.

You can now copy and paste the entire graphic, or directly assign it to a symbol: p = <graphic>

Also, see: http://www.wolfram.com/broadcast/screencasts/howtoeditmathematicagraphics/




回答2:


I sometimes find it useful to replace the entire rule/option, rather than just the RHS of the rule. For instance, something like this, based on your example:

myplot /. (PlotStyle -> x__) -> (PlotStyle -> myRestyle[x]);

I also like that this avoids the problem of appending duplicates of the option.

This is handy for restyling other objects, such as:

styledText /. (FontSize->x_) -> (FontSize->2x)


来源:https://stackoverflow.com/questions/5644801/tweaking-style-attributes-of-existing-graphics-objects-in-mathematica

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!