Tweaking style/attributes of existing Graphics objects in Mathematica
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], Dashin开发者_Python百科g[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)?
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.
The plotted lines of the functions (
Sin[x]
,Cos[x]
) and their styles are "hard coded" intoLine
objects, whichGraphics
can understand.Auxiliary settings such as
Axes -> True
,PlotLabel -> "Sine Cosecant Plot"
andAxesStyle -> Orange
are understood byGraphics
directly, without conversion, and therefore remain within themyplot
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/
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)
精彩评论