22
$\begingroup$

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.

$\endgroup$
  • 3
    $\begingroup$ Internal`InheritedBlock[{Plot}, SetOptions[Plot, Frame -> True]; Plot[x, {x, 0, 1}] ] like this? $\endgroup$ – Kuba Jan 23 '17 at 14:51
  • 1
    $\begingroup$ Why not cache the list returned by Options[Plot], do your custom stuff, and use SetOptions[] again at the end? $\endgroup$ – J. M. is away Jan 23 '17 at 14:55
  • 2
    $\begingroup$ @Kuba, I guess Internal`WithLocalSettings[] is also a possibility. $\endgroup$ – J. M. is away Jan 23 '17 at 15:06
  • 3
    $\begingroup$ For the plotting problem in particular, one could define a plot theme. $\endgroup$ – Michael E2 Apr 13 '17 at 15:36
  • 2
    $\begingroup$ @MichaelE2 Wolfram should support an easy way to create new themes. $\endgroup$ – becko Apr 13 '17 at 15:47
23
$\begingroup$

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. Carl notes in a comment below that the advantage of using this function is that any code in the first and third arguments are uninterruptible.

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}}

(See also this SO thread and this example usage by Oleksandr.)

$\endgroup$
  • 9
    $\begingroup$ 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 Nasser's 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. $\endgroup$ – Carl Woll Jan 23 '17 at 17:11
  • $\begingroup$ "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! $\endgroup$ – J. M. is away Jan 23 '17 at 17:22
  • $\begingroup$ @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). $\endgroup$ – Kuba Jan 24 '17 at 6:32
15
$\begingroup$

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.

$\endgroup$
  • 2
    $\begingroup$ 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. $\endgroup$ – Kuba Jan 24 '17 at 6:30
  • 1
    $\begingroup$ @Kuba not unreasonable, but not my department. $\endgroup$ – rcollyer Jan 24 '17 at 12:41
  • 1
    $\begingroup$ I have a particular project in which I want to change the options of a function locally in a ScheduledTaskObject without the options change altering subsequent calls in the FrontEnd. This solution seems to do the trick for me. $\endgroup$ – bobthechemist Apr 13 '17 at 14:07
12
$\begingroup$

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

$\endgroup$
  • 2
    $\begingroup$ Or use a List instead of a Sequence: opts = {PlotStyle -> Red, Frame -> True} $\endgroup$ – Bob Hanlon Jan 23 '17 at 15:18
  • $\begingroup$ @becko - it's shorter ... but flavor to taste. $\endgroup$ – Bob Hanlon Jan 23 '17 at 20:09
  • $\begingroup$ @becko - on my system (11.0.1 for Mac OS X x86 (64-bit)) the Evaluate is still needed. $\endgroup$ – Bob Hanlon Jan 23 '17 at 20:17
  • 2
    $\begingroup$ If you use With instead of Module, you can eliminate the Evaluate. $\endgroup$ – rcollyer Jan 24 '17 at 4:11
9
$\begingroup$

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

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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