6
$\begingroup$

I need to add a small graphics on top of a larger one, and the small graphics should stick very close to the large one, with their axis aligned. Here's a minimal code to work with, using some elements from this question/answer :

How to make a plot on top of other plot?

Intensity[p_, q_, phi_] := Plot[
    (If[p > 0, Sin[2Pi p^2 x]/(2Pi p^2 x), 1]Cos[2Pi p^2 q x + phi/2])^2,
    {x, -30, 30},
    PlotPoints -> 400,
    MaxRecursion -> 4,
    PlotRange -> All,
    PlotRange -> {{-30, 30}, {0, 1}},
    Axes -> False,
    AspectRatio -> 1,
    Frame -> True,
    ImageSize -> {600, 600}
]

LumIntensity[p_, q_, phi_] := DensityPlot[
    (If[p > 0, Sin[2Pi p^2 x]/(2Pi p^2 x), 1]Cos[2Pi p^2 q x + phi/2])^2,
    {x, -30, 30}, {y, 0, 1}, 
    AspectRatio -> 0.1,
    PlotPoints -> {1000, 2},
    Frame -> None, 
    ImageSize -> 600
]

GraphicsColumn[
    {LumIntensity[0.25, 5, 0], Intensity[0.25, 5, 0]},
    Spacings -> 0
]

Here's what I want to achieve (which the question/answer above don't solve) :

interference

Also, how can I add a black frame around the small graphics ? Using Frame -> True or Framed[...] gives an ugly output.

The combination would be used for a Manipulate box, since p, q and phi are variables.

EDIT : Actually, it would be better if the small graphics was placed at the bottom of the large one.

$\endgroup$
  • 1
    $\begingroup$ Try Frame -> TrueFrameTicks -> None, PlotRange -> Full $\endgroup$ – chris Apr 3 '16 at 16:20
  • $\begingroup$ @chris, thanks, this works for the frame around the small graphics. $\endgroup$ – Cham Apr 3 '16 at 16:24
  • $\begingroup$ Using Epilog in the large graphics, and Inset for the small graphics could partially solve my issue. Unfortunately, if I resize the large graphics by hand, the small one isn't well aligned anymore with the marks on the large graphics. $\endgroup$ – Cham Apr 3 '16 at 16:28
9
$\begingroup$

I think it may perhaps be easier just to combine plots and modify (e.g. suppress unnecessary frame ticks). I post this as a motivating answer rather than definitive answer. li is a modified version of OP function:

li[p_, q_, phi_, {l_, u_}] := 
 DensityPlot[(If[p > 0, Sin[2 Pi p^2 x]/(2 Pi p^2 x), 1] Cos[
      2 Pi p^2 q x + phi/2])^2, {x, -30, 30}, {y, l, u}, 
  AspectRatio -> 0.1, PlotPoints -> {1000, 2}, Frame -> None, 
  ImageSize -> 600]
Manipulate[
 Show[Intensity[0.25, 5, 0], li[0.25, 5, 0, {l, u}]], {l, -1, 0, 
  Appearance -> "Labeled"}, {{u, -0.5}, -1, 0, 
  Appearance -> "Labeled"}]

enter image description here

$\endgroup$
  • $\begingroup$ Very nice ! Thanks a lot ! $\endgroup$ – Cham Apr 4 '16 at 12:56
  • $\begingroup$ This solution is simpler and more natural than my Inset + Epilog solution. The code is a bit shorter. I'll adopt it as the solution to the problem. $\endgroup$ – Cham Apr 4 '16 at 13:22
  • $\begingroup$ @Cham thank you. My aim with Manipulate was to find the desired bounds. I am glad it was helpful. :) $\endgroup$ – ubpdqn Apr 4 '16 at 13:24
4
$\begingroup$

This is a partial solution, using Epilog and Inset. It has an alignment problem, especially after we resize the picture by hand inside the Manipulate box. Also, without resizing the whole, playing with the parameters may give an alignment problem after a while. How to fix this ?

LumIntensity[x_, p_, q_] := (If[p > 0, Sin[2Pi p^2 x]/(2Pi p^2 x), 1]Cos[2Pi p^2 q x])^2

Intensity1[p_, q_] := Inset[
    DensityPlot[LumIntensity[x, p, q],
    {x, -30, 30}, {y, 0, 1},
    ColorFunction -> GrayLevel,
    AspectRatio -> 0.1,
    Frame -> None,
    PlotPoints -> {1000, 2},
    ImageSize -> 600],
    {0, -0.1}
]

Intensity2[p_, q_] := Plot[
    LumIntensity[x, p, q],
    {x, -30, 30},
    PlotPoints -> 400,
    MaxRecursion -> 4,
    PlotRange -> {{-30, 30}, {-0.2, 1}},
    Axes -> None,
    AspectRatio -> 1,
    Frame -> True,
    Epilog -> Intensity1[p, q],
    ImageSize -> {600, 600}
]

Manipulate[
    Intensity2[p, q],
    {{p, 0.25, Style["Diffraction : p", 12]}, 0, 0.5, 0.01,
        ImageSize -> Large, Appearance -> "Labeled"},
    {{q, 1, Style["Interference : q", 12]}, 1, 10, 0.01,
        ImageSize -> Large, Appearance -> "Labeled"},
    ControlPlacement -> Bottom,
    FrameMargins -> None
]

Preview :

Box

So how can I make the bottom graphics always well aligned with the graphics above it, even after we resive the whole by hand ?

$\endgroup$
  • $\begingroup$ I think I've found it. In the Inset, I just need to replace the coordinates {0, -0.1} to {0, -0.1}, {0, 0.5}, 60. The result is superb ! $\endgroup$ – Cham Apr 3 '16 at 19:04
1
$\begingroup$

Just going to throw this in to the mix. When I saw this question, it immediately seemed perfect for Jens's function, which I modified and used previously, and in fact I have it defined in my init.m because I use it with such regularity.

I have modified the original function to respect the individual aspect ratios of the constituent plots, and the definition is in the pastebin linked below. It's a reasonably large but robust function, which I've used to combine plots for publication for years now.

Using the functions defined in the OP, this is the plotting code,

<< "http://pastebin.com/raw/1uhTgyuJ"
plotGrid[{{LumIntensity[0.25, 5, 0]}, {Intensity[0.25, 5, 
    0]}}, 600, 660, "KeepAR" -> True]

enter image description here

The plot can be interactively resized with the mouse and the overall appearance remains unchanged.

$\endgroup$
0
$\begingroup$

This can be achieved by matching a few layout options between the two charts. Namely, ImageSize, ImageMargins, ImagePadding, PlotRange, and PlotRangePadding. Scaled and Automatic can be used to simplify selection.

With

f[p_, q_, phi_, x_] := 
   (If[p > 0, Sin[2 Pi p^2 x]/(2 Pi p^2 x), 1] Cos[2 Pi p^2 q x + phi/2])^2

alignment = 
 Sequence[ImageSize -> {600, Automatic}, 
  ImageMargins -> 0, 
  PlotRangePadding -> Scaled[.02], 
  ImagePadding -> {{Scaled[.03], Scaled[.01]}, {Automatic, Automatic}}];

Then

Column[
 {DensityPlot[f[.25, 5, 0, x], {x, -30, 30}, {y, 0, 1}, 
   PlotPoints -> {1000, 2}, Frame -> None, AspectRatio -> .1, 
   Evaluate@alignment],
  Plot[f[.25, 5, 0, x], {x, -30, 30}, 
   PlotRange -> Full, Frame -> True, 
   Evaluate@alignment]},
 Spacings -> Scaled[.0005]]

enter image description here

Since we want to align along the x-axis we only need the x-axis plot range, size, padding, and margin to match between the two plots. The plot range is matched in the plot calls so alignment only contains items for size, padding, and margin. With this the plots have the same width and amount of whitespace along the x-axis and so they align.

Hope this helps.

$\endgroup$
  • $\begingroup$ I'm using Column instead of GraphicsColumn as I'm currently using 10.3 and it appears that GraphicsColumn is ignoring its Spacings option. $\endgroup$ – Edmund Apr 4 '16 at 13:14

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.