I want to use gridlines to create an effect of millimeter graphing paper on a 2d graph, to show how multi-variable function depends on 1 variable. The scales of different va
I think FindDivisions[ ] is what you're after:
FindDivisions[{xmin,xmax},n] finds a list of about n "nice" numbers that divide the interval around xmin to xmax into equally spaced parts.
getTicks[x_, y_] := Flatten@FindDivisions[#, {10}] & /@ FromTo[x, y]
getGrid [x_,y_] := FindDivisions[{x,y},{10,5}]/.
{r__,{s__}}:>Join@@{s,{#,{Gray,Thick}}&/@r}
If you use the same function for FrameTicks
and Gridlines
, they'll line up.
See FrameTicks, and GridLines. I think you'll need ImageMargins
for the border.
Don't use FrameTicks but shift the grid correctly. This is a first approach. Dinner waits.
getGrid[min_, max_] :=
Module[{step, i},
Print[{min, max}];
step = 1/100;
Table[
{
Floor[min, 0.1] + i*step,
If[Equal[Mod[i, 10], 0], Directive[Gray, Thick, Opacity[0.5]],
If[Equal[Mod[i, 5], 0], Directive[Gray, Opacity[0.5]],
Directive[LightGray, Opacity[0.5]]
]
]
},
{i, 1, (Ceiling[max, 0.1] - Floor[min, 0.1])/step // Round}
]
]
Use an AspectRatio that's appropriate for the grid (probably the ratio of x and y ranges)
After-dinner update
To make it more robust for different value ranges (per your comment) I generate the ticks that would be chosen by ListPlot
and base my steps on that:
getGrid[min_, max_] :=
Module[{step, i,j},
i = Cases[(Ticks /.
AbsoluteOptions[ListPlot[{{min, min}, {max, max}}],
Ticks])[[1]], {a_, ___, {_, AbsoluteThickness[0.25`]}} :> a];
step = i[[2]] - i[[1]];
Table[
{
i[[1]] + j*step/10,
If[Equal[Mod[j, 10], 0], Directive[Gray, Thick, Opacity[0.5]],
If[Equal[Mod[j, 5], 0], Directive[Gray, Opacity[0.5]],
Directive[LightGray, Opacity[0.5]]
]
]
},
{j, 0, 10 Length[i]}
]
]
and getting the aspect ratio which yields a square raster
getAspect[{{minX_, maxX_}, {minY_, maxY_}}] :=
Module[{stepx, stepy, i, rx, ry},
i = (Ticks /.AbsoluteOptions[ListPlot[{{minX, minY}, {maxX, maxY}}], Ticks]);
rx = Cases[i[[1]], {a_, ___, {_, AbsoluteThickness[0.25`]}} :> a];
stepx = rx[[2]] - rx[[1]];
ry = Cases[i[[2]], {a_, ___, {_, AbsoluteThickness[0.25`]}} :> a];
stepy = ry[[2]] - ry[[1]];
((maxY - minY)/stepy)/((maxX - minX)/stepx)
]
Test
ELP[x_, y_, ex_, ey_, name_] :=
ErrorListPlot[Cmb[x, y, ex, ey], PlotLabel -> name, Joined -> True,
Frame -> True, GridLines -> getGrid, ImageSize -> {600},
PlotRangePadding -> 0, AspectRatio -> getAspect[FromTo[x, y]],
PlotRange -> FromTo[x, y]]
ELP[{4124961/25000000, 27573001/100000000, 9162729/25000000,
44635761/100000000, 15737089/25000000, 829921/1562500,
4405801/4000000, 23068809/25000000, 329386201/100000000,
58079641/100000000}, {1/10, 1/5, 3/10, 2/5, 3/5, 1/2, 1/2, 1/2, 1/2,
1/2}, {2031/(250000 Sqrt[10]), 5251/(500000 Sqrt[10]),
3027/(250000 Sqrt[10]), 1/100000 6681/(500000 Sqrt[10]),
3967/(250000 Sqrt[10]), 911/(62500 Sqrt[10]),
2099/(100000 Sqrt[10]), 4803/(250000 Sqrt[10]),
18149/(500000 Sqrt[10]), 7621/(500000 Sqrt[10])}, {1/2000, 1/1000,
3/2000, 1/500, 3/1000, 1/400, 1/400, 1/400, 1/400, 1/400}, "T2, m"]
Here I divide the y-values by 20 and multiplied the x-values by 10000 to show the grid is still good:
Final update (I hope)
This uses FindDivisions as suggested by belisarius. However, I used the three level line structure standard for milimeter paper as requested by Margus:
getGrid[x_, y_] :=
FindDivisions[{x, y}, {10, 2, 5}] /. {r_, s_, t_} :>
Join[
{#, Directive[Gray, Thick, Opacity[0.5]]} & /@ r,
{#, Directive[Gray, Opacity[0.5]]} & /@ Union[Flatten[s]],
{#, Directive[LightGray, Opacity[0.5]]} & /@ Union[Flatten[t]]
]
and
getAspect[{{minX_, maxX_}, {minY_, maxY_}}] :=
Module[{stepx, stepy},
stepx = (#[[2]] - #[[1]]) &@FindDivisions[{minX, maxX}, 10];
stepy = (#[[2]] - #[[1]]) &@FindDivisions[{minY, maxY}, 10];
((maxY - minY)/stepy)/((maxX - minX)/stepx)
]
WARNING!!!
I just noticed that if you have this in MMA:
and you copy it to SO (just ctrl-c ctrl-v), you get this:
(maxY - minY)/stepy/(maxX - minX)/stepx
which is not mathematically equivalent. It should be this:
((maxY - minY)*stepx)/((maxX - minX)*stepy)
I corrected this in the code above, but it has been posted wrong for half a day while working correctly on my computer. Thought that it would be good to mention this.