3
$\begingroup$

I am interested in making multiple plots with the same amount of "GridLines" and "FrameTicks", particularly for plot-range -> all. Is there a straightforward way to do this and set it as a default option?

Here are some images as an example: enter image description here enter image description here

And here's some code to reproduce something similar without the dashed lines.

SetOptions[Plot, Frame -> True, Axes -> False, 
  LabelStyle -> {FontFamily -> "Arial", FontSize -> 30}, 
  GridLines -> Automatic, GridLinesStyle -> LightGray, 
  PlotStyle -> {{ColorData[101, "ColorList"], 
     Thickness[.015]}, {Black, Thickness[.03], Dotted  }, {Black , 
     Thickness[.015]}}];

analyticalSol = (100000000 ((0.` + 600.` I) + 
      1000000 \[CapitalDelta]pMHz) (2.25`*^12 + 
      2 ((0.` - 600.` I) - 
         1000000 \[CapitalDelta]pMHz) (1206000000 I + 
         2 (1163000000 + 
            1000000 \[CapitalDelta]pMHz))) Sqrt[\[Pi] Log[
      2]])/(((1206000000 + 
         2 I (-1163000000 - 
            1000000 \[CapitalDelta]pMHz)) (144000000000000 + 
         2 (600.` - 1000000 I \[CapitalDelta]pMHz) (1206000000 - 
            2000000 I \[CapitalDelta]pMHz)) + 
      2.25`*^12 (1206000000 - 
         2000000 I \[CapitalDelta]pMHz)) (600.` - 
      1000000 I \[CapitalDelta]pMHz))

g11 = Plot[
  Re[ComplexExpand[analyticalSol]], {\[CapitalDelta]pMHz, -10, 10}, 
  Frame -> True, FrameLabel -> {{None, None}, {None, None}}, 
  GridLines -> Automatic, GridLinesStyle -> LightGray, 
  BaseStyle -> 12, PlotRange -> All, ImageSize -> {300, 300}]
g12 = Plot[
  Im[ComplexExpand[analyticalSol]], {\[CapitalDelta]pMHz, -10, 10}, 
  Frame -> True, FrameLabel -> {{None, None}, {None, None}}, 
  GridLines -> Automatic, GridLinesStyle -> LightGray, 
  BaseStyle -> 12, PlotRange -> All, ImageSize -> {300, 300}, 
  FrameTicks -> {{{0, .06, .12}, None}, {{-10, 0, 10}, None}}]
$\endgroup$
  • $\begingroup$ You can always do SetOptions[Plot,.....] and set in there the common options for all you plots? $\endgroup$ – Nasser Jun 12 at 4:29
  • $\begingroup$ @Nasser, I'm using SetOptions already, as you can see in the code. The issue is that I need to know the plotrange in order to have a specific number of grid lines. $\endgroup$ – Steven Sagona Jun 12 at 4:30
  • $\begingroup$ I meant to fix the actual values in the SetOptions. But it seems you want something else. If each plot will have different plot range, not sure how this will work out. sounds hard problem. $\endgroup$ – Nasser Jun 12 at 4:34
4
$\begingroup$
ClearAll[setPlotOptions]
setPlotOptions[major : (_Integer | _List | Automatic) : 6, minor_: 6] := 
 SetOptions[Plot, {Frame -> True, Axes -> False, 
   LabelStyle -> {FontFamily -> "Arial", FontSize -> 18}, 
   GridLinesStyle -> LightGray, 
   Sequence @@ Switch[Head[major], 
     Integer, {FrameTicks -> 
       {{Charting`ScaledTicks["Linear"][#, #2, {major, minor}] &, Automatic}, 
       {Charting`ScaledTicks["Linear"][#, #2, {major, minor}] &, Automatic}}, 
        GridLines -> {FindDivisions[{#, #2}, major] &, FindDivisions[{#, #2}, major] &}}, 
     List, {FrameTicks -> major, GridLines -> {major[[2, 1]], major[[1, 1]]}},
      _, {FrameTicks -> Automatic, GridLines -> Automatic}]}]

Examples:

setPlotOptions[];

Plot[2 Sin[x], {x, -2 Pi, 2 Pi}, ImageSize -> Large]

enter image description here

Plot[x Sin[10 x], {x, -5 Pi, 5 Pi}, ImageSize -> Large]

enter image description here

setPlotOptions[20, 1];

Plot[2 Sin[x], {x, -2 Pi, 2 Pi}, ImageSize -> Large]

enter image description here

Plot[x Sin[10 x], {x, -5 Pi, 5 Pi}, ImageSize -> Large]

enter image description here

setPlotOptions[{{Subdivide[-1., 2, 4], Automatic}, {Range[-10, 10], Automatic}}];

Plot[2 Sin[x], {x, -2 Pi, 2 Pi}, ImageSize -> Large]

enter image description here

Plot[x Sin[10 x]/5, {x, -5 Pi, 5 Pi}, ImageSize -> Large]

enter image description here

You can override any of the options set by SetOptions inside Plot. For example,

Plot[x Sin[10 x]/5, {x, -5 Pi, 5 Pi}, ImageSize -> Large, 
 FrameTicks -> Automatic,
 GridLinesStyle -> Directive[Dashed, Red]]

enter image description here

| improve this answer | |
$\endgroup$
  • $\begingroup$ Thanks for your answer. Do you think you could explain some of the syntax? I'm not sure I understand "[major : (Integer | _List | Automatic) : 6, minor: 6]" I haven't seen something like this before. $\endgroup$ – Steven Sagona Jun 12 at 19:50
  • $\begingroup$ @StevenSagona, the function setPlotOptions takes two optional arguments . When provided, the first argument should be an Integer or a list or Automatic. If no argument is provided (the function is called as setPlotOptions[]) the two arguments take the _default value 6. If it is called with a single argument (e.g. setPlotOptions[10]) the scond argument takes the default value 6. See the tutorial Optional And Default Arguments in the docs. $\endgroup$ – kglr Jun 12 at 20:17
2
$\begingroup$

An alternative, perhaps more convenient, approach is to define a wrapper function that propagates the option value for FrameTicks to set the option value for GridLines.

While we are at it, (1) we can inject additional options in the definition of the wrapper function so that we don't have set them again in Plot, and (2) we can trick FrameTicks to "accept" option values that it would normally not accept (such as FrameTicks -> {10, 5} to specify (up to) 10 automatically selected major ticks on the horizontal axis and 5 on the vertical axis, or, FrameTicks -> {{6, 4},{10,5}} to specify (up to) 6 major and 4 minor ticks on the horizontal axis and 10 major 5 minor ticks on the vertical axis).

We use TagSetDelayed to define the function propagateOV :

ClearAll[propagateOV]
propagateOV /: Rule[FrameTicks, propagateOV[a_]] := 
 {ImageSize -> Medium, Frame -> True, Axes -> False, GridLinesStyle -> LightGray, 
  Rule[FrameTicks, 
   Switch[a, 
     _Integer, {{Charting`ScaledTicks["Linear"][#, #2, a] &, Automatic}, 
          {Charting`ScaledTicks["Linear"][#, #2, a] &, Automatic}},
    {_Integer, _Integer}, {{Charting`ScaledTicks["Linear"][#, #2, Last@a] &, Automatic}, 
          {Charting`ScaledTicks["Linear"][#, #2, First@a] &, Automatic}},
    {{_Integer, _Integer}, _} | {_, {_Integer, Integer}}, 
        {{Charting`ScaledTicks["Linear"][#, #2, Last@a] &, Automatic}, 
        {Charting`ScaledTicks["Linear"][#, #2, First@a] &, Automatic}} ,
    _, a]], 
  Rule[GridLines, 
   Switch[a,
     _Integer, {FindDivisions[{#, #2}, a] &, FindDivisions[{#, #2}, a] &}, 
    {_Integer, _Integer}, 
        {FindDivisions[{#, #2}, First@a] &, FindDivisions[{#, #2}, Last@a]&} , 
    {{_Integer, _Integer}, {_Integer, _Integer}}, 
        {FindDivisions[{#, #2}, a[[1, 1]]] &, FindDivisions[{#, #2}, a[[2, 1]]] &} ,
    {{_List, _}, {_List, _}}, a[[{2,1}, 1]], 
     _, Automatic]]}

Examples:

Set (up to) 15 (automatically selected) major ticks for both axes (left panel) and (up to) 15 major ticks for horizontal and 5 for the vertical axes (right panel) and set the GridLines accordingly:

Row[{Plot[x Sin[10 x], {x, -5 Pi, 5 Pi}, FrameTicks -> propagateOV@15], 
  Plot[x Sin[10 x], {x, -5 Pi, 5 Pi}, FrameTicks -> propagateOV@{15, 5}]}]

enter image description here

Specify different major and minor ticks for horizontal and vertical axes and set the GridLines at major ticks:

Row[{Plot[x Sin[10 x], {x, -5 Pi, 5 Pi},  FrameTicks -> propagateOV@{{15, 5}, {5, 5}}], 
  Plot[x Sin[10 x], {x, -5 Pi, 5 Pi}, FrameTicks -> propagateOV@{{15, 1}, {5, 1}}]}]

enter image description here

Automatic frame ticks with (right panel) and without (left panel) the propagateOV wrapper:

Row[{Plot[x Sin[10 x], {x, -5 Pi, 5 Pi}, Frame -> True, 
    ImageSize -> Medium, FrameTicks -> Automatic],
  Plot[x Sin[10 x], {x, -5 Pi, 5 Pi}, FrameTicks -> propagateOV@Automatic]}]

enter image description here

User-specified lists of ticks with (right panel) and without (left panel) the propagateOV wrapper:

Row[{Plot[x Sin[10 x], {x, -5 Pi, 5 Pi}, Frame -> True,  ImageSize -> Medium,
    FrameTicks -> {{Range[-10, 10, 2], Automatic}, {Range[-5, 15, 3], Automatic}}], 
  Plot[x Sin[10 x], {x, -5 Pi, 5 Pi}, 
   FrameTicks -> 
     propagateOV@{{Range[-10, 10, 2], Automatic}, {Range[-5, 15, 3], Automatic}}]}]

![enter image description here

Finally, you can over-ride the options set by propagateOV by simply putting the options you want to override before the option FrameTicks:

Plot[x Sin[10 x], {x, -5 Pi, 5 Pi}, 
 Axes -> True, ImageSize -> Large, GridLinesStyle -> Green,
 FrameTicks -> propagateOV@{15, 5}]

enter image description here

| improve this answer | |
$\endgroup$
1
$\begingroup$

The GridLines specification can be a function. It will be passed the min and max values of the variable in the direction it applies to, and returns gridline positions (and other style specifications, if you want). That gives you access to the plot range from within the plotting function.

You can use Subdivide with a specified number of gridlines to generate a constant number of gridlines at varying spacing depending on the plot range:

Plot[Sin[x], {x, 0, 10}, GridLines -> {(Subdivide[##, 4][[2 ;; -2]] &), None}]
Plot[Sin[x/2], {x, 0, 100}, GridLines -> {(Subdivide[##, 4][[2 ;; -2]] &), None}]

small range large range

Subdivide will always return the first and last values in the range, but I think you do not want those, looking at your plots; that’s the reason for the Part selection.

Another option would be FindDivisions but I find that often that function's choice of "nice" division points does not agree with mine.

| improve this answer | |
$\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.