12
$\begingroup$

NB: I am aware that "plots" are graphics too, so the title would be more precisely worded if "graphics" were replaced by "non-plot graphics".


EDIT: I have edited my original example to make the problems with the solutions proposed so far more evident.


For example, let plot be this plot:

plot = Plot[{0.5 Cos[4 Pi x], x}, {x, 0, 0.5}, ImageSize -> Small]

Mathematica graphics

...and graphic be this disk:

graphic = Graphics[{LightGray, Disk[{-1, -0.25}, 0.2]}, ImageSize -> Tiny, Frame->True]

Mathematica graphics

I want to superimpose plot and graphic so that

  1. they share the same coordinate system (including aspect ratio)
  2. all the components of plot and graphics (including axes, frames, tick-marks, etc.) are represented in the resulting image.

More generally, I want to superimpose an arbitrary sequence of plots and graphics so that the two requirements above are satisfied.

Although this follows directly from (1), let me explicitly state that the ordering of the items in the sequence of plots and graphics should have no effect in the relative placement of the superimposed items.


The Overlay command meets requirement 2 only:

Overlay[{graphic, plot}]

Mathematica graphics

IMPORTANT: Even though the placement and proportions it produces are completely off, Overlay gets right the aspect of faithfully preserving the axes, frames, ticks, etc. of its components.


The Show command meets requirement 1 only:

Show[{graphic, plot}, ImageSize -> Small]

Mathematica graphics

The frame in Show's output is spurious: it does not correspond to graphic's original frame. Furthermore, plot's axes are gone.

A more subtle (and serious) problem with Show is that it is not commutative:

Show[{plot, graphic}, ImageSize -> Small]

Mathematica graphics

In this example, flipping the order of items in the call to Show causes one of the items is no longer shown.


The result from Show looks much closer to the desired result, but is missing plot's axes, ticks, etc.

IOW, plot's contribution to the final result should look like this:

Mathematica graphics

Note, in particular, the extents of the axes.


NB: In this example, the x and y coordinates are scaled equally on the screen (and, therefore, in the desired final result, graphic's disk looks circular and plot's orange line has a 45-degree angle on the screen). In general, however, the scaling of the x and y coordinates need not be equal. The only requirement is that the scaling, whatever it is, applies equally to both plot and graphic.

$\endgroup$
5
  • 1
    $\begingroup$ Show[plot, graphic, PlotRange -> All, plot[[2]]]? $\endgroup$
    – kglr
    Feb 9, 2017 at 20:21
  • $\begingroup$ Instead of plot[[2]], Options[plot] can also be used. $\endgroup$
    – C. E.
    Feb 9, 2017 at 20:23
  • $\begingroup$ Neither of the solutions offered deal with the general case (which I've just made more prominent in the post). $\endgroup$
    – kjo
    Feb 9, 2017 at 20:44
  • 2
    $\begingroup$ What you need is FullGraphics but it seems to be a abandoned function. I have tried a little bit to use it for your problem but it is not satisfactory $\endgroup$
    – andre314
    Feb 9, 2017 at 21:41
  • $\begingroup$ @andre: IMHO, Mathematica is becoming less and less useful with every new version :/ . $\endgroup$
    – kjo
    Feb 9, 2017 at 21:54

3 Answers 3

10
+100
$\begingroup$

The problem you will run into by keeping the frame/axis ticks & labels is that the space outside of the bounds of the frame/axis is not measured in the coordinate space of the graphic. It is instead measured in printer (or desktop publishing) points.

Inset can inset a graphic sized to the coordinate space but that size includes the space padded on (in printer points) to make room for the frame/axis ticks & labels. A method to convert this printer points padding into units of the coordinate space such that it would be useful to Inset is not immediately clear.

However, if you were willing to forgo some tick labels with the option to support their absence by a frame then you can achieve the superimposition.

superimposeGraphics[graphics_List, opts : OptionsPattern[Graphics]] :=
 Graphics[
  With[{rng = First@Values@AbsoluteOptions[#, PlotRange]},
     Inset[#, rng[[All, 1]], rng[[All, 1]], Flatten[Differences /@ rng]]
     ] & /@ (Show[#, AspectRatio -> Automatic, 
       PlotRangePadding -> None, ImagePadding -> None] & /@ graphics)
  ,
  opts,
  PlotRange -> (MapThread[#1[#2] &, {{Min, Max}, #}] & /@
     Transpose[
      Flatten[Values@AbsoluteOptions[graphics, PlotRange], 1], {3, 1, 2}])
  ]

superimposeGraphics removes the PlotRangePadding (in coordinate space units) and ImagePadding (in printer points) from the graphics. The graphic is now bounded by its frame and only contains its plot range.ImageMargins could also be set to zero if you like. The AspectRatio to Automatic so that no stretching will occur from the inset sizing. Now these can be Inset into the graphic and sized to the coordinate space of the enclosing Graphics. The PlotRange is set to include all graphics.

superimposeGraphics[{plot, graphic}, ImageSize -> Large]

Mathematica graphics

or

superimposeGraphics[{plot, graphic}, ImageSize -> Large, 
 Frame -> True, GridLines -> Automatic, GridLinesStyle -> LightGray]

Mathematica graphics

Hope this helps.

$\endgroup$
8
$\begingroup$

Use Prolog or Epilog

Plot[{0.5 Cos[4 Pi x], x}, {x, 0, 0.5},
 ImageSize -> Small,
 Prolog -> {LightGray, Disk[{0.45, -0.25}, 0.2]},
 PlotRange -> {{0, 0.65}, {-0.5, 0.5}},
 AspectRatio -> 1/0.65]

enter image description here

$\endgroup$
7
$\begingroup$
Show[graphic, plot,  PlotRange -> All, plot[[2]]]

Mathematica graphics

Show[ graphic, plot, AspectRatio -> Automatic, PlotRange -> All, plot[[2]]]

Mathematica graphics

As noted by @C.E. in a comment, you can also use Options[plot] instead of plot[[2]].

If it is OK if some items obscure others, then as noted by @AlbertRetey in a comment, you just need

Show[plot, graphic, AspectRatio -> Automatic, PlotRange -> All]

Mathematica graphics

$\endgroup$
6
  • 1
    $\begingroup$ if you change the order you won't need the addition of plot[[2]]. The convention is (not sure whether that is documented or not) that the options of the first graphics are used unless they are explicitly overwritten with options. So Show[{plot, graphic}, AspectRatio -> Automatic, PlotRange -> All] will work as well. $\endgroup$ Feb 9, 2017 at 20:55
  • 1
    $\begingroup$ just looked it up: from the documentation of Show: "The lists of non-default options in the g_i are concatenated." $\endgroup$ Feb 9, 2017 at 20:56
  • 1
    $\begingroup$ @AlbertRetey, you are right, Show takes the unspecified options from the first argument. Not sure if this what the OP asked, but the reason I did not change the order of graphic and plot is to have disk appear below the plot lines. $\endgroup$
    – kglr
    Feb 9, 2017 at 21:18
  • $\begingroup$ yes, that is a problem I also just have seen. I don't exactly remember why, but I got into the habit of using Prolog and Epilog in such cases, maybe it was because of these peculiarities with Show... $\endgroup$ Feb 9, 2017 at 21:23
  • $\begingroup$ @kglr: It's ok if some items obscure others. $\endgroup$
    – kjo
    Feb 9, 2017 at 21:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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