19
$\begingroup$

I'd like to create a custom function that does essentially the same as a core function of mathematica but uses different default settings.

Example: I want a Plot function that uses Mathematica's core Plot function but uses different default settings. I don't want to use SetOptions[Plot, ...] because I don't want to override anything for the core Plot function. Instead of this I want to build a custom function PlotFramed[x^2,{x,-5,5}] that points to Plot[x^2, {x,-5,5}, Frame->True, GridLines->Automatic].

I also want the function to be able to override my default settings. So PlotFramed[x^2, {x,-5,5}, GridLines->None] should return the results from Plot[x^2, {x,-5,5}, Frame->True, GridLines->None].

And I want to use additional options that are not set by default as in the normal Plot function. So PlotFramed[x^2, {x,-5,5}, PlotStyle->Dashed] should point to Plot[x^2, {x,-5,5}, Frame->True, GridLines->Automatic, PlotStyle->Dashed].

The reason for this is that when writing reports (in LaTeX) I have to add several options to the plot function to make the font-size bigger, add a grid, etc pp. Using the idea above I could write a custom Plot function that I can use when generating output for the report and otherwise use Mathematica's core function since everything is fine with it when working inside Mathematica.

Can anyone tell me how to do this? This would be awesome. Thanks in advance!

$\endgroup$
1

3 Answers 3

23
$\begingroup$

I have proposed a different solution exactly for this sort of situations. You don't have to create a new function with it, but rather you create an environment such that when your function is executed in it, the options you desire get passed to it. So, it is the same idea, but automated one step further.

Here is the (modified) code for the option configurator:

ClearAll[setOptionConfiguration, getOptionConfiguration,withOptionConfiguration];
SetAttributes[withOptionConfiguration, HoldFirst];
Module[{optionConfiguration}, 
  optionConfiguration[_][_] = {};
  setOptionConfiguration[f_, tag_, {opts___?OptionQ}] := 
     optionConfiguration[f][tag] = FilterRules[{opts}, Options[f]];
  getOptionConfiguration[f_, tag_] := optionConfiguration[f][tag];
  withOptionConfiguration[f_[args___], tag_] :=
    optionConfiguration[f][tag] /. {opts___} :> f[args, opts];];

Here is how one can use it: first create the option configuration with some name (e.g. "framed"):

setOptionConfiguration[Plot, "framed", 
   {Frame -> True, GridLines -> Automatic, PlotStyle -> Dashed}]

Now you can use it:

withOptionConfiguration[Plot[x^2, {x, -5, 5}], "framed"]

You can also create an environment short-cut:

framed = Function[code, withOptionConfiguration[code, "framed"],  HoldFirst];

enter image description here

and then use it as

framed@Plot[x^2, {x, -5, 5}]

to get the same as before.

The advantage of this approach is that you can use the same tag (name) for the option configuration, for many different functions, at once.

$\endgroup$
2
  • $\begingroup$ Wow, this looks very impressive. I tried it and it worked very well. Thanks for this additional solution. I'll try to understand exactly what you're doing there (still learning Mathematica) and then I'll probably using this solution since it's easy to expand it also to other functions using setOptionConfiguration[#, "framed", {Frame -> True, GridLines -> Automatic, PlotStyle -> Dashed}] & /@ {Plot, ListPlot} and I can use the normal syntax of any function without even think about it. At the end it simply is putting framed@ in front of it. Cool solution, thank you. $\endgroup$
    – dotcs
    Apr 4, 2013 at 20:56
  • $\begingroup$ @chromate Good if it works for you. $\endgroup$ Apr 5, 2013 at 7:51
12
$\begingroup$
PlotFramed[f_, opts___] :=
 Plot[f@x, {x, -5, 5}, Frame -> True, opts]

Supply any option in place of opts, or you can leave it blank.

PlotFramed[#^2 &, {
  GridLines -> Automatic,
  PlotStyle -> Directive[Thick, Red, Dashed]}]

plot

$\endgroup$
6
  • $\begingroup$ Nice! Thank you very much for your solution. I tried the following to keep the range of x variable and it worked: PlotFramed[f_, x_, opts___] := Module[{}, Plot[f@First@x, x, Frame -> True, PlotStyle -> Dashed, opts] ]. Now I can do the following: PlotFramed[#^2 &, {x, -5, 5}, GridLines -> Automatic] Sorry that I can't upvote your post but I need at least 15 reputation. :/ $\endgroup$
    – dotcs
    Apr 4, 2013 at 19:15
  • 1
    $\begingroup$ Another comment on this. I found out that the opts and the default variables have to be changed in the function definition. So it should look like PlotFramed[f_, opts___] := Plot[f@x, {x, -5, 5}, opts, Frame -> True] otherwise it is not possible to override the default values. $\endgroup$
    – dotcs
    Apr 4, 2013 at 19:43
  • $\begingroup$ @chromate Story of my life, girls used to say that to me. :) Why do you have Module if you don't localize any variables (ie. empty {})? That's messy, f@First@x isn't it, although there's probably nothing wrong with that, but define range like PlotFramed[f_, {x1_, x2_}, opts___], and use x in the definition only. $\endgroup$
    – BoLe
    Apr 4, 2013 at 19:43
  • $\begingroup$ I just used Module because I planned something bigger with the function. In this case it's not necessary, you're right. I used f@First@x because I tried to keep the Plot syntax so that I can just copy everything I have in a Plot function by just rewrite Plot to PlotFramed. Okay I have to change the x to # but the rest then stays the same. Is there any option to keep the x, too? $\endgroup$
    – dotcs
    Apr 4, 2013 at 19:53
  • $\begingroup$ @chromate Define it like PlotFramed[f_, x_, opts___] := Plot[f, {x, -5, 5}, opts] and you can make a call PlotFramed[x^2, x]. $\endgroup$
    – BoLe
    Apr 4, 2013 at 19:59
7
$\begingroup$

I addressed this specific problem fairly extensively in my answer: Functions with Options

Please read that answer for important additional points. In brief:

SetAttributes[PlotFramed, HoldAll]

Options[PlotFramed] = {Frame -> True, GridLines -> Automatic};

PlotFramed[args__] := Plot[args, ##] & @@ Options[PlotFramed]

Now these work as you desire:

PlotFramed[x^2, {x, -5, 5}]

PlotFramed[x^2, {x, -5, 5}, GridLines -> None]

PlotFramed[x^2, {x, -5, 5}, PlotStyle -> Dashed]

enter image description here

You can easily change or add to the options of PlotFramed with the canonical methods:

SetOptions[PlotFramed, Frame -> {0, 1, 0, 1}];
AppendTo[Options[PlotFramed], GridLinesStyle -> Red];

PlotFramed[x^2, {x, -5, 5}]

enter image description here


You may also be interested in this example of plot style customization:
How to change the default ColorData used in Mathematica's Plot?


In recent versions of Mathematica creating a custom PlotTheme may serve your needs:

$\endgroup$
3
  • $\begingroup$ Thank you Mr.Wizard for this solution. It works exactly as you described it. Since I want to have multiple functions behave the same way (Plot, LogPlot, ListPlot, ListLogPlot, etc.) I'll stick with Leonid Shifrin's solution. But I'll keep your solution also in mind because it's very lightweight. $\endgroup$
    – dotcs
    Apr 5, 2013 at 13:50
  • $\begingroup$ @chromate You're welcome. When you say you want to have all those functions behave the same way, can you be more specific? Should they all have the same options or unique to each modified function, e.g. LogPlotFramed, etc.? $\endgroup$
    – Mr.Wizard
    Apr 5, 2013 at 14:18
  • $\begingroup$ They should have most of the options in common but not all of them. A problematic example is GridLines->Automatic and GridLinesStyle->Directive[Gray,Dotted] which I use for my custom Plot function. But for LogLogPlot all the grid lines drive me crazy. So I override GridLines->None for LogLogPlot and LogPlot and so on. I did something similar for PlotStyle where I differ between list plots and non-list plots. For list plots I have to adjust the PointSize whereas PointSize is irrelevant for non list functions. I think it could also be done with your solution. $\endgroup$
    – dotcs
    Apr 5, 2013 at 15:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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