How do I make framed plots the same size?
As Jagra said, the usual solution is to manually specify the ImagePadding
values. The problem is that if the plot or frame labels are too large, a fixed ImagePadding
may cut them off.
But can we automate this?
Ideally what we would do is:
Create the two plots of fixed vertical size and retrieve their vertical
ImagePadding
Change the
ImagePadding
of both to use the larger value. This will ensure that they have the same size while no labels are cut off.
So how do we measure the ImagePadding
of an existing plot? This is unfortunately tricky as the value depends on the size of the plot. Since the plots will be stacked horizontally, we need to fix the vertical image size before trying to retrieve the padding. But here's a pretty useful solution (that I use regularly):
- Retrieving the ImagePadding in absolute units
First note that I'm fixing the vertical size instead of the horizontal one. This allows the graphics to have differing horizontal sizes if necessary while still aligning perfectly when stacked in a row.
verticalSize = 250;
plot1 = Plot[x^2, {x, 0, 1}, Frame -> True,
FrameLabel -> {"x (nm)", "y (nm)"},
BaseStyle -> {FontFamily -> "Arial", 20},
ImageSize -> {Automatic, verticalSize}];
plot2 = Plot[x^2, {x, -10, 10}, PlotRange -> {-10, 1000},
Frame -> True,
FrameLabel -> {"\!\(\*SuperscriptBox[SubscriptBox[\"x\", \"a\"], \
\"2\"]\) (\!\(\*SuperscriptBox[\"nm\", \"2\"]\))",
"\!\(\*SuperscriptBox[SubscriptBox[\"y\", \"b\"], \"2\"]\) \
(\!\(\*SuperscriptBox[\"nm\", \"2\"]\))"},
BaseStyle -> {FontFamily -> "Arial", 20},
ImageSize -> {Automatic, verticalSize}];
This function measures the padding (based on @Heike's code):
getPadding[g_] := Module[{im},
im = Image[Show[g, LabelStyle -> White, Background -> White]];
BorderDimensions[im]
]
Now let's choose the larger one of both the top and bottom paddings of the two figures. This will give us the minimum image padding that still does not cut off labels.
{p1h, p1v} = getPadding[plot1];
{p2h, p2v} = getPadding[plot2];
verticalPadding = Max /@ Transpose[{p1v, p2v}]
Row[{
Show[plot1, ImagePadding -> {p1h, verticalPadding}],
Show[plot2, ImagePadding -> {p2h, verticalPadding}]
}]
The problem with this approach is that often one would wish to fix the horizontal size of the whole graphic (to fit the text width of the document). I admit that when I had the same problem I did this by iteratively refining the sizes, which is not very elegant, but produces good results automatically.
ImagePadding should get you most of want you want:
imgSize = 475;
imagePadding = {{100, 10}, {25, 10}};
plot1 = Plot[x^2, {x, 0, 1}, Frame -> True,
FrameLabel -> {"x (nm)", "y (nm)"},
BaseStyle -> {FontFamily -> "Arial", 20}, ImageSize -> imgSize,
ImagePadding -> imagePadding];
plot2 = Plot[x^2, {x, -10, 10}, PlotRange -> {-10, 1000},
Frame -> True,
FrameLabel -> {"\!\(\*SuperscriptBox[SubscriptBox[\"x\", \"a\"], \
\"2\"]\) (\!\(\*SuperscriptBox[\"nm\", \"2\"]\))",
"\!\(\*SuperscriptBox[SubscriptBox[\"y\", \"b\"], \"2\"]\) \
(\!\(\*SuperscriptBox[\"nm\", \"2\"]\))"},
BaseStyle -> {FontFamily -> "Arial", 20}, ImageSize -> imgSize,
ImagePadding -> imagePadding];
Grid[{{plot1, plot2}}]
You can play around with the values to get what you need. Hmmm? I wonder if one could automate the selection of the optimum values?
Use the undocumented (but not likely to go away) ImageSize
syntax ImageSize -> Automatic -> width
:
imgSize = Automatic -> 300;
Then, your code produces:
Grid[{{plot1, plot2}}]