# How to adjust the correct ImageSize between two plots

Let's consider the following simple plot

P0 = Plot[Sin[x], {x, -7, 7}, Frame -> True, Axes -> False, PlotLabel ->
Style["Test 1", FontSize -> 20, Black, FontFamily -> "Helvetica"],
AspectRatio -> 1, ImageSize -> 550];


The second one is much more complicated ad we need to create some data in order to replicate the situation

n = 5000;
data = Table[{RandomReal[], RandomReal[], RandomReal[{10^-2, 10^4}],
RandomInteger[{0, 2}]}, {i, 1, n}];


Define a color function

valrange = {-2, 4};
data[[All, 3]] = Rescale[Log10[data[[All, 3]]], valrange];
colfunc[x_, cf_] := If[x[[4]] == 0, Gray, ColorData[cf][1 - x[[3]]]];


Create a colrbar

Clear[colorbar]
colorbar[{min_, max_}, colorFunction_: Automatic, divs_: 150] :=
DensityPlot[y, {x, 0, 0.1}, {y, min, max}, AspectRatio -> 10,
PlotRangePadding -> 0, PlotPoints -> {2, divs}, MaxRecursion -> 0,
Frame -> True, FrameLabel -> {{None, "test"}, {None, None}},
LabelStyle -> Directive[FontFamily -> "Helvetica", 17],
FrameTicks -> {{None, All}, {None, None}},
FrameTicksStyle -> Directive[FontFamily -> "Helvetica", 15, Plain],
ColorFunction -> colorFunction]


A simple contour

C0 = ContourPlot[x^2 + y^2, {x, -1, 1}, {y, -1, 1}, Contours -> {0.5},
ContourStyle -> {{Black, Thickness[0.005]}}, AspectRatio -> 1,
ContourShading -> False, PlotPoints -> 200,
PerformanceGoal -> "Quality"];


and finally the modified density plot

With[{opts = {ImageSize -> {Automatic, 550}}, cf = "Rainbow"},
Row[{Show[
ListPlot[List /@ data[[All, {1, 2}]],
PlotStyle -> ({PointSize[0.005], colfunc[#, cf]} & /@ data),
AspectRatio -> 1, Frame -> True, RotateLabel -> False,
Axes -> None, FrameTicks -> True, FrameLabel -> {"x", "y"},
LabelStyle -> Directive[FontFamily -> "Helvetica", 20],
ImagePadding -> {{60, 20}, {60, 20}}, opts,
PlotLabel -> Style["Test 2", FontSize -> 20, Black,
FontFamily -> "Helvetica"]], C0, PlotRange -> 0.9,
PlotRangeClipping -> True],
Show[colorbar[valrange, ColorData[cf][1 - #] &],
ImagePadding -> {{20, 60}, {60, 40}}, opts]}]]


There are two issues regarding this second complicated plot:

(a). For large data sets, (n > 10000) the programs needs more than 10 minutes so as to create the plot! Is there any way to speed up the process?

(b). Even though I set PlotRange -> 0.9, PlotRangeClipping -> True, we see that the frame in all directions does not end at exactly 0.9 but in 0.9 + dx. Why?

Now, if we put together the two plot

it becomes evident that size of them do not match. For both plots I used ImageSize -> 550 but it seems that the second one (the complicated) is smaller. I suspect, that this has to so with the colorbar it carries together. So, my question is: how can I get the second plot match in size with the first?

EDIT

Apparently, each (x,y) point should be treated as a separate list by using List /@ data[[All, {1, 2}]]. That's the reason why the code is very slow when we have many points. Unfortunately and strangely enough I cannot use ListDensityPlot simply because stupidly it joins by default the points without giving you an option for that!

• no problems here - the top of the "Test" text aligns with the top of the left plot. Nov 20, 2013 at 9:36
• @cormullion See my update. They actually do not align. I would like the square frame of the second plot has the same size as the first one and also the titles to align each other. Nov 20, 2013 at 9:46
• @Vaggelis_Z concerning (a) I think you should replace in your plotting function List /@ data[[All, {1, 2}]] with simple data[[All, {1, 2}]] Nov 20, 2013 at 10:11
• To prevent padding the plot range, use PlotRangePadding -> 0 Nov 20, 2013 at 10:58
• As for the size, you have set P0 to have a width of 550 pixels, and the complex plot to have a height of 550 pixels, with lots of image padding. If you want the frames to line up use the same settings for ImageSize and ImagePadding in P0 as you do in the complex plot. Nov 20, 2013 at 11:00

I noticed that the output of your colfunc produces symbolic expressions that certainly slow down evaluation. This is caused by Log10.

Try colfunc[#, "Rainbow"] & /@ data to check it out.

So try to change to data[[All, 3]] = Rescale[Log10[data[[All, 3]]] // N, valrange];

Adding //N speeds up colfunc by a factor of x7.

Also changing colfunc[#, cf]} & /@ data to colfunc[#, cf]} & /@ 1.data you will gain another 2x.

With these changes in my machine it took 10 seconds to plot for n=10000.

I also noticed that your routines are memory consuming so you could try to use packed arrays also.

Pasting changed code :

data[[All, 3]] = Rescale[Log10[data[[All, 3]]] // N, valrange];

With[{opts = {ImageSize -> {Automatic, 550}}, cf = "Rainbow"},
Row[{Show[
ListPlot[List /@ data[[All, {1, 2}]],
PlotStyle -> ({PointSize[0.005], colfunc[#, cf]} & /@ 1. data),
AspectRatio -> 1, Frame -> True, RotateLabel -> False,
Axes -> None, FrameTicks -> True, FrameLabel -> {"x", "y"},
LabelStyle -> Directive[FontFamily -> "Helvetica", 20],
ImagePadding -> {{60, 20}, {60, 20}}, opts,
PlotLabel ->
Style["Test 2", FontSize -> 20, Black,
FontFamily -> "Helvetica"]], C0, PlotRange -> 0.9,
PlotRangeClipping -> True],
Show[colorbar[valrange, ColorData[cf][1 - #] &],
ImagePadding -> {{20, 60}, {60, 40}}, opts]}]]

• I' m getting some errors now! Just to be sure what we are changing please, post the complete part of the code With[ ... ] Nov 20, 2013 at 12:19
• In my machine (Win XP, Mathematica, v9.0.0, Dual Core 2.2GHz) n = 10000 took about 30 sec. My real data files have at least 50000 points. Nov 20, 2013 at 12:33
• In my machine (WIN7, Mathematica, v9.0.0 clock at 3Ghz , for n=50000 it took 510 sec. I am testing with PackedArrays , hold on... Nov 20, 2013 at 12:52
• Check also this link : mathematica.stackexchange.com/questions/1300/… Nov 20, 2013 at 13:42
• For n=50000 my machine needs 735 sec. Surely it must be a way to speed up the process. Nov 20, 2013 at 14:28