Is there a way to SetOptions locally? For example, I have a Module and inside it I am doing a lot of Plots with similar options. If I do a SetOptions[Plot, ...] inside the Module, the change propagates outside. I don't like this because I have other Modules where I am doing other plots with different options.

Is there a way to do a SetOptions[Plot, ...] that only affects "local" plots (say inside a Module, but I am open to any scoping construct)? Here Plot is only an example. In general I want to set options locally for any symbol.

share|improve this question
2  
Internal`InheritedBlock[{Plot}, SetOptions[Plot, Frame -> True]; Plot[x, {x, 0, 1}] ] like this? – Kuba 16 hours ago
1  
Why not cache the list returned by Options[Plot], do your custom stuff, and use SetOptions[] again at the end? – J. M. 16 hours ago
1  
@Kuba, I guess Internal`WithLocalSettings[] is also a possibility. – J. M. 16 hours ago
    
@J.M. I just saw your comment. Yes, this is what I thought to do also. good idea :) – Nasser 16 hours ago
1  
Yet another alternative is to create local option configurations. This method does not modify global state at all, even locally, but rather passes all necessary options explicitly as local rules. – Leonid Shifrin 15 hours ago

Usual caveats about using undocumented functions aside, here is how one might use Internal`WithLocalSettings[]:

With[{plotOptions = Options[Plot]}, 
     Internal`WithLocalSettings[SetOptions[Plot, PlotStyle -> Green]], 
                                Plot[Sin[x], {x, -π, π}],
                                SetOptions[Plot, plotOptions]]]

but I do not think this to be any better than Nasser's proposal. As can be surmised from how it was used above, you can think of the three arguments of Internal`WithLocalSettings[] as three stages: setup, body, and clean-up.

A more usual case for its use would be for localizing changes to system settings that are not easily accessible to SetOptions[]. Using the Wizard's code from here as an example:

With[{spopt = SystemOptions["SparseArrayOptions"]},
     Internal`WithLocalSettings[
              SetSystemOptions["SparseArrayOptions" -> {"TreatRepeatedEntries" -> 1}],
              ind = {{3, 1}, {3, 3}, {1, 3}, {2, 1}, {3, 2}, {3, 1},
                     {3, 2}, {3, 3}, {1, 3}, {3, 1}};
              val = {1, 1, 3, 0, 3, 4, 3, 1, 1, 1};
              SparseArray[ind -> val] // Normal,
              SetSystemOptions[spopt]]]
   {{0, 0, 4}, {0, 0, 0}, {6, 6, 2}}
share|improve this answer
7  
I would say using Internal`WithLocalSettings is better than using Module, because the first and third arguments of Internal`WithLocalSettings are not interruptible, and always happen. If you add a Pause[10] to the @Nasser example and abort the computation, you will see that the PlotStyle remains Green. Also, it's convenient that the second argument is the output, so one doesn't need to store the result so that it can be returned as the output after the cleanup occurs. – Carl Woll 14 hours ago
    
"Also, it's convenient that the second argument is the output, so one doesn't need to store the result so that it can be returned as the output after the cleanup occurs." - that was certainly a convenient feature for me, but I definitely didn't know about the non-interruptibility. Thanks @Carl! – J. M. 14 hours ago
    
@CarlWoll Maybe for you but if it eventually break your app you can't even complain because you used undocumented function. (the point here is to push it to System` since everyone is using it anyway). – Kuba 1 hour ago

Just define your options as sequence held in a local variable.

Module[{opts = Sequence[PlotStyle -> Red, Frame -> True]},
  Plot[Sin[2 π x], {x, 0, 1}, Evaluate @ opts]]

plot

share|improve this answer
2  
Or use a List instead of a Sequence: opts = {PlotStyle -> Red, Frame -> True} – Bob Hanlon 16 hours ago
    
@becko - it's shorter ... but flavor to taste. – Bob Hanlon 11 hours ago
    
@becko - on my system (11.0.1 for Mac OS X x86 (64-bit)) the Evaluate is still needed. – Bob Hanlon 11 hours ago
1  
If you use With instead of Module, you can eliminate the Evaluate. – rcollyer 3 hours ago

This is a simple solution. The idea is to save the Plot options on entry, and restore it on leaving the module to whatever it was

f := Module[{savedOpt = Options[Plot]},
  SetOptions[Plot, PlotStyle -> Green];
  Print@Plot[Sin[x], {x, -Pi, Pi}];
  SetOptions[Plot, savedOpt]
  ]

Now global Plot options are not changed. Test:

Mathematica graphics

share|improve this answer

I have used several methods, including the ones in the other answers. I have found that the simplest method is Internal`InheritedBlock as it allows for temporary changes to a symbol to be made, including changes to Options. For example,

Internal`InheritedBlock[{Plot},
  SetOptions[Plot, PlotStyle -> Red, Frame -> True];
  Plot[Sin[x], {x, 0, 2 Pi}]
]
Plot[Sin[x], {x, 0, 2 Pi}]

enter image description here

Obviously, this has the most utility when you are making multiple plots, but this illustrates the point.

share|improve this answer
    
Why don't you (not you personally ofc) document them then? Just add where it would not be a good idea to use it, if there are any problems. It is not like System` is perfect anyway. – Kuba 1 hour ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.