1
$\begingroup$

I have several plots with different y-axis ranges. This is the main reason I want the content being aligned Right in a GraphicsColumn so that the plot frames are nicely aligned. Example

GraphicsColumn[{
  Plot[Sin[x], {x, 0, 2 Pi}, Frame->True, AspectRatio -> 1/5],
  Plot[100000 Sin[x], {x, 0, 2 Pi}, Frame->True, AspectRatio -> 1/5],
  Plot[100 Sin[x], {x, 0, 2 Pi}, Frame->True, AspectRatio -> 1/5]
}, Right]

This results in an awkward image

right aligned graphics column

The plots seem to be aligned Right, just as requested, but the alignment position seems to be running down the middle of the resulting image.

First let's fix the image size by adding ImageSize->1000. This results in

larger graphics column

The unusually large empty spaces on both side of the image remain. I can get rid of them, e.g. by post-processing the resulting pdf files with pdfcrop but that somehow defeats the purpose of having all this graphics machinery in the Mathematica language.

Questions:

How to get the last version of the image but with the bounding box tightly wrapped around the content?

Is there another, more elegant way to align several Plot-frames in a column or 2D grid?

$\endgroup$
3
$\begingroup$

There is a work around. We can Frame all the boxes and making the color of those frames white.

GraphicsColumn[{Plot[Sin[x], {x, 0, 2 Pi}, Frame -> True, AspectRatio -> 1/5], 
  Plot[100000 Sin[x], {x, 0, 2 Pi}, Frame -> True, AspectRatio -> 1/5], 
  Plot[100 Sin[x], {x, 0, 2 Pi}, Frame -> True, AspectRatio -> 1/5]}, 
 Alignment -> Right, Frame -> All, FrameStyle -> White]

enter image description here

$\endgroup$
  • 2
    $\begingroup$ Interesting that this should fix it. By the way FrameStyle -> Opacity[0] might be a better choice. $\endgroup$ – Mr.Wizard Feb 18 '17 at 14:41
  • $\begingroup$ @Mr.Wizard I didn't knew that. Thanks $\endgroup$ – zhk Feb 18 '17 at 15:06
2
$\begingroup$

Manual resizing

GraphicsRow, GraphicsColumn, and GraphicsGrid always give me trouble. I don't know how to fix this programmatically, but fortunately there is another way. You can manually rescale the frame by clicking on the graphic so that a gray frame appears:

enter image description here

Then putting the mouse pointer over the right center control point, holding Ctrl, and dragging:

enter image description here

PlotRange

A bit of experimentation shows that it is possible to fix this with Show and PlotRange.

myGraphicsColumn[gr : {__Graphics}, opts___] :=
  Show[
    GraphicsColumn[gr, opts]
    , PlotRange -> {{Automatic, # + 10}, Automatic}
  ] & @ Max[ First @ Rasterize[#, "RasterSize"] & /@ gr ]

Example:

myGraphicsColumn[
 {Plot[Sin[x], {x, 0, 2 Pi}, Frame -> True, AspectRatio -> 1/5], 
  Plot[100000 Sin[x], {x, 0, 2 Pi}, Frame -> True, AspectRatio -> 1/5], 
  Plot[100 Sin[x], {x, 0, 2 Pi}, Frame -> True, AspectRatio -> 1/5]}
 , Right
]

Origin of the problem

It is interesting that MMM's Frame work-around solves this. It seems that the frames are drawn directly as Line expressions showing that GraphicsColumn knows the right size of things. The problem appears to stem from the automatic PlotRange chosen by Graphics in the absence of any "tangible" primitives, meaning those beside Inset.

The form of the output is something like this:

p1 = Plot[Sin[x], {x, 0, 2 Pi}, Frame -> True, AspectRatio -> 1/5];

Graphics[{Inset[p1, {369, 0}, ImageScaled[{1, 0.5}], {360, 72}]}]

enter image description here

Note all the extra space. This persists even with zero paddings:

Graphics[{Inset[p1, {369, 0}, ImageScaled[{1, 0.5}], {360, 72}]}
 , PlotRangePadding -> 0
 , ImagePadding -> 0
 , ImageMargins -> 0
]

enter image description here

A "tangible" primitive fixes it.

Graphics[{
  {LightRed, Rectangle[{30, -40}, {370, 40}]},
  Inset[p1, {369, 0}, ImageScaled[{1, 0.5}], {360, 72}]
}]

enter image description here

$\endgroup$
  • $\begingroup$ +1 for introducing the new term "tangible primitive". An addition: without "tangible" primitives and with default PlotRange -> All FrontEnd always sets PlotRange -> {{-1, 1}, {-1, 1}} (it is easy to check by adding Frame -> True). Note that when coordinates in the primitive are given in Scaled or Offset form, this primitive is "intangible". $\endgroup$ – Alexey Popkov Feb 19 '17 at 6:23
0
$\begingroup$

Based on @LLlAMnYP analysis here, a right aligned version of his undistortedGraphicsColumn is then

MyGraphicsColumnRight[item_List] := 
  Module[{size = Map[ImageDimensions, item], width}, 
    width = Max[size[[;;, 1]]];
    size = size[[;;, 2]];
    Graphics[
      Table[
        Inset[item[[i]], {0, -Total[size[[;;i]]]}, ImageScaled[{1, 0}]],
        {i, Length[item]}
      ],
      ImageSize->{width, Total[size]},
      ImagePadding->None, 
      PlotRange->{{-width, 0}, {-Total[size], 0}}, 
      AspectRatio->Total[size]/width,
      PlotRangePadding->None
    ]
  ]

Using it as in

MyGraphicsColumnRight[{
  Plot[Sin[x], {x, 0, 2 Pi}, Frame->True, ImageSize->500,  AspectRatio->1/5],
  Plot[100000 Sin[x], {x, 0, 2 Pi}, Frame->True, ImageSize->519, AspectRatio->1/5],
  Plot[100 Sin[x], {x, 0, 2 Pi}, Frame->True, ImageSize->503, AspectRatio->1/5]
}]

then gives us this right-aligned image:

right-aligned

Nevertheless, the size of individual plots has to be manually adjusted (see ImageSize-> above) to get the perfect alignment of all the frames of corresponding plots.

$\endgroup$
  • $\begingroup$ Your's (and @LLlAMnYP's in the linked post) usage of AspectRatio isn't quite correct since you don't take into account that ImagePadding (which is non-zero in your case) is excluded from AspectRatio. This is the most probable reason why you have to adjust ImageSizes manually. Please see this dedicated thread for detailed description of how AspectRatio actually works. $\endgroup$ – Alexey Popkov Feb 19 '17 at 5:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.