# How can I make a grid of plots with no spacing, and have the plots line up perfectly?

I am making a bunch of two dimensional plots and I would like to have them arranged in a grid with no space in between them. That is, I want their frames touching each other.

My problem is twofold. First I don't know how to get the plots to have a consistent size. When I try to give the plots the same size via ImageSize, it applies the size to the overall image, including the tick marks and labels. But when I have two different plots, one with tick labels and one without, giving the same value to ImageSize doesn't give the result I'm looking for.

Secondly, I want to get rid of any white space around the images such that when I give Grid the option Spacings ->{0,0} there really is no visible space between the plots.

In the example code I use the CustomTicks package.

(*an example of what I might plot, simple sum of two dimensional \
Lorentzians*)
lzn[x_, w_, g_] := (x - w + I g)^-1;
exampledata2D =
Table[Re[lzn[w1, .2, .1] lzn[w2, .3, .2] +
lzn[w1, .4, .1] lzn[w2, .8, .1] +
lzn[w1, .8, .2] lzn[w2, .4, .2]], {w1, 0, 1, .01}, {w2, 0,
1, .01}];
<< "CustomTicks";
standardticks = LinTicks[0, 1, .2, 4];
(*I don't want the last tick label for one plot overlapping with the \
first tick label of the plot right next to it.*)
ticks2 = LinTicks[0, 1, .2, 4, ShowLast -> False];
(*Custom plotting function so I don't have to reprint the same \
options over and over *)
plottingfunction[list_, plotopts : OptionsPattern[]] :=
ListContourPlot[list,
Evaluate[FilterRules[{plotopts}, Options[ListContourPlot]]],
Contours -> 30, PlotRange -> All, DataRange -> {{0, 1}, {0, 1}},
BaseStyle -> 18,
ColorFunction -> (Blend[{Red, Orange, Yellow, Green, Blue,
Darker[Blue]}, #] &)];

bottomleft =
plottingfunction[exampledata2D,
FrameTicks -> {{ticks2, StripTickLabels[standardticks]}, {ticks2,
StripTickLabels[standardticks]}}];
bottomright =
plottingfunction[exampledata2D,
FrameTicks -> {{StripTickLabels[standardticks],
StripTickLabels[standardticks]}, {standardticks,
StripTickLabels[standardticks]}}];
topleft =
plottingfunction[exampledata2D,
FrameTicks -> {{ticks2,
StripTickLabels[standardticks]}, {StripTickLabels[
standardticks], StripTickLabels[standardticks]}}];
topright =
plottingfunction[exampledata2D,
FrameTicks -> {{StripTickLabels[standardticks],
StripTickLabels[standardticks]}, {StripTickLabels[
standardticks], StripTickLabels[standardticks]}}];

Grid[{{topleft, topright}, {bottomleft, bottomright}},
BaseStyle -> ImageSizeMultipliers -> 1, Spacings -> {0, 0}]

• I realize this may be a duplicate, but I didn't find the answer when I searched around. Commented Nov 20, 2013 at 19:25
• You may be interested in grid full of plots. Fix ImageSize, fix AspectRation, focus on FrameTicks, use ImagePadding for plot and Spacing for Grid.
– Kuba
Commented Nov 20, 2013 at 19:30
• A good solution might be to use the LevelScheme package which can handle these things. This answer mentions it. Commented Nov 20, 2013 at 19:34
• More resources here and here. Commented Nov 20, 2013 at 19:50
• @Szabolcs, if you added the disclaimer at the top, could you change it to point to grid full of plots instead of Aligning plot axes in a graphics object as that is the post I used to solve this. Thanks. Commented Nov 20, 2013 at 20:33

Another way to do this is to use the SciDraw package (LevelScheme successor). (Note: I'm still learning to use this package and I may not be doing things in the most efficient way. Also, the package is still in beta as of November 2013.)

This is the plot we're going to have in the grid:

plot = plottingfunction[exampledata2D];

<<SciDraw

A very simple way to construct the grid, exploiting the fact that all nine subplots are identical, is the following:

Figure[
Multipanel[
{
FigurePanel[{FigGraphics[plot]}, All, (* "All" means evaluate this for all subplots *)
PanelLetterTextColor -> White];
},

Dimensions -> {3, 3}  (* a 3 by 3 grid *)
],

CanvasSize -> 8 {1, 1} (* the canvas aspect ratio sets the subplot aspect ratio too *)
]

Of course in practical situations the subplots are all different. Here's a more realistic way to do it which is convenient if the subplots are different but have the same plot range:

DefineStyle["ContourArray",
{
FigurePanel -> {
XPlotRange -> {0, 1}, (* these need to be set if different from {0,1} *)
YPlotRange -> {0, 1},
YTickLabelRange -> {0.2, 1},
XTickLabelRange -> {0.2, 1},
PanelLetterTextColor -> White }
}
]

Figure[
Multipanel[
{
FigurePanel[{FigGraphics[plot]}, {1, 1}];
FigurePanel[{FigGraphics[plot]}, {1, 2}];
FigurePanel[{FigGraphics[plot]}, {1, 3}];
FigurePanel[{FigGraphics[plot]}, {2, 1}];
FigurePanel[{FigGraphics[plot]}, {2, 2}];
FigurePanel[{FigGraphics[plot]}, {2, 3}];
FigurePanel[{FigGraphics[plot]}, {3, 1}, XTickLabelRange -> All];
FigurePanel[{FigGraphics[plot]}, {3, 2}];
FigurePanel[{FigGraphics[plot]}, {3, 3}];
},

Dimensions -> {3, 3}
],

Style -> "ContourArray",
CanvasSize -> 8 {1, 1}
]

Note how the tick label overlap was solved: the default tick range was set to $0.2 - 1.0$ and it was overridden on the bottom left panel only.

To disable the automatic panel lettering, use PanelLetter -> None in the style.

• Wow! SciDraw is the answer to my Mathematica plotting prayers ... I want to go have a cry I am so happy. Commented Dec 9, 2013 at 0:42
• I notice that the documentation and your example makes the arguments to *Panel's as a list of a single element, using ; to separate the different plotting directives. I find you can just change this to a list (which seems more natural to me). Is there any reason for the ; style or is it just preference? Things like this always suggest my lack of deep MMA knowledge... Commented Dec 9, 2013 at 2:24
• To answer my own question ... the use of ; is stylistic and is explained in section 10.1 of the SciDraw documentation. Commented Dec 9, 2013 at 3:32
• Great answer, great package, just one question I can't figure out: How can I set AspectRatio to something other than 1 while using Multipanel or FigurePanel? SciDraw seems to override it as an argument given to the 'plottingfunction' (i.e. ListPlot), and I can't find any helpful option in the SciDraw documentation. For reference, I'm using v.0.0.7 of SciDraw.
– Max
Commented Feb 26, 2017 at 0:37
• @Max You can adjust the CanvasSize option at the very end. Commented Feb 26, 2017 at 7:37

Thanks to Kuba and Szabolcs for pointing out many related posts. I recognize that LevelScheme is probably the best way to go here, but at the moment I don't have the time to learn everything I need in order to use it.

I am going to use Jens's solution from this page, but I have to remove the certain tick labels so that they don't overlap each other.

(*an example of what I might plot, simple sum of two dimensional \
Lorentzians*)
lzn[x_, w_, g_] := (x - w + I g)^-1;
exampledata2D =
Table[Re[lzn[w1, .2, .1] lzn[w2, .3, .2] +
lzn[w1, .4, .1] lzn[w2, .8, .1] +
lzn[w1, .8, .2] lzn[w2, .4, .2]], {w1, 0, 1, .01}, {w2, 0,
1, .01}];
<< "CustomTicks`";
tickbottom = LinTicks[-1, 1, .5, 5, ShowLast -> False];
ticktop = LinTicks[-1, 1, .5, 5, ShowFirst -> False];
tickmiddle =
LinTicks[-1, 1, .5, 5, ShowFirst -> False, ShowLast -> False];
standardticks = LinTicks[-1, 1, .5, 5];
plottingfunction[list_, horizontalposition_, verticalposition_,
plotopts : OptionsPattern[]] :=
ListContourPlot[list,
Evaluate[FilterRules[{plotopts}, Options[ListContourPlot]]],
Contours -> 30, DataRange -> {{-1, 1}, {-1, 1}}, BaseStyle -> 18,
ColorFunction -> (Blend[{Red, Orange, Yellow, Green, Blue,
Darker[Blue]}, #] &), PlotRangePadding -> None,
PlotRange -> All,
FrameTicks -> {{Which[verticalposition == "Top", ticktop,
verticalposition == "Middle", tickmiddle,
verticalposition == "Bottom", tickbottom],
StripTickLabels[standardticks]}, {If[
verticalposition == "Bottom",
Which[horizontalposition == "Right", ticktop,
horizontalposition == "Middle", tickmiddle,
horizontalposition == "Left", tickbottom],
StripTickLabels[standardticks]],
StripTickLabels[standardticks]}}];

plotGrid[l_List, w_, h_, opts : OptionsPattern[]] :=
topPadding = 0, widths, heights, dimensions, positions,
frameOptions =
FilterRules[{opts},
FilterRules[Options[Graphics],
Except[{ImagePadding, Frame, FrameTicks}]]]}, {ny, nx} =
Dimensions[l];
widths = (w - 2 sidePadding)/nx Table[1, {nx}];
heights = (h - 2 sidePadding)/ny Table[1, {ny}];
positions =
Transpose@
Partition[
Tuples[Prepend[Accumulate[Most[#]], 0] & /@ {widths, heights}],
ny];
Graphics[
Table[Inset[
Show[l[[ny - j + 1, i]],
positions[[j, i]], {Left, Bottom}, {widths[[i]],
heights[[j]]}], {i, 1, nx}, {j, 1, ny}],
PlotRange -> {{0, w}, {0, h}}, ImageSize -> {w, h},
Evaluate@Apply[Sequence, frameOptions]]]

plotGrid[Table[
plottingfunction[exampledata2D, h,
v], {v, {"Top", "Middle", "Bottom"}}, {h, {"Left", "Middle",
"Right"}}], 1000, 1000]

I'm not 100% happy with the way it looks, with the missing tick labels, but it is better than having the labels overlap or get cut off.

• I use LevelScheme a lot and I don't suggest using it for this. Your solution is far better/simpler, IMO. LevelScheme works great for line plots, but I've found using 2D plots (images/ArrayPlots/ContourPlots, etc.) to be a royal pain in the ass. I'm not sure what you mean by "missing tick labels" — they all seem to be there. Am I missing something?
– rm -rf
Commented Nov 22, 2013 at 14:21
• @rm-rf, in order that the 1.0 label from one plot not overlap with the -1.0 label from the next, I've omitted them both for the points where the plots meet. I don't think that's the most aesthetically pleasing solution. I'd rather omit one label or the other, but not both. The problem with that is that both labels hang off the side just a bit, so when I trim the plots so they don't have any padding, it cuts off a portion of the label I'm keeping. I think what I'll do now is just add the 1.0 in that spot in Inkscape, since I'm going to be adding plot labels in Inkscape anyways. Commented Nov 22, 2013 at 17:15
• That is a problem I've often faced (and I like making plots like these). My approaches to fix this has been to either label the x/y ticks in detail on the lower left plot and nowhere else (but tick marks still present) or to have a gap between the plots to accommodate the two extra ticks (I usually favour the second approach). Having only one of them would be a tad confusing, especially if the plots are arranged without any gap.
– rm -rf
Commented Nov 22, 2013 at 18:58
• This question is closed, but I really wanted to add another solution using the SciDraw package, that I am learning to use now. I added the solution to your answer, just edit it to your liking ... @rm-rf with this package it turned out to be relatively convenient. Commented Nov 27, 2013 at 17:28
• @Szabolcs The question is open now. Feel free to post an answer
– rm -rf
Commented Nov 27, 2013 at 17:46