# 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. Nov 20 '13 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
Nov 20 '13 at 19:30
• A good solution might be to use the LevelScheme package which can handle these things. This answer mentions it. Nov 20 '13 at 19:34
• More resources here and here. Nov 20 '13 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. Nov 20 '13 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. Dec 9 '13 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... Dec 9 '13 at 2:24
• To answer my own question ... the use of ; is stylistic and is explained in section 10.1 of the SciDraw documentation. Dec 9 '13 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
Feb 26 '17 at 0:37
• @Max You can adjust the CanvasSize option at the very end. Feb 26 '17 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
Nov 22 '13 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. Nov 22 '13 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
Nov 22 '13 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. Nov 27 '13 at 17:28
• @Szabolcs The question is open now. Feel free to post an answer
– rm -rf
Nov 27 '13 at 17:46