# Drawing outside Plot area

I want to programmatically draw some objects outside the Plot area in my Plot's Epilog, like in this dummy: I found PlotRangeClipping and hoped that would be the solution, but setting it to False only gives me a very little bit of extra space: How can I get that extra space?

For extra credit: I want my arrows smaller and my text bigger. ArrowHeads give all kinds of sizes, but I can't seem to control it. Also, my text is positioned a bit more to the right than the arrows, but I'd like to align it left, so that I can use the same X-coordinate. Lastly, below's my code. Constructive criticism is welcome, if you're curious enough to read it :-).

dc1 = 0.1; dc2 = 0.6; period = 1; rc = 3; y0 = dc1; mint = -4; maxt = 20;
maxt2 = maxt - (maxt - mint)/5; tsplit = 0;
rectangleWave[t_, period_, duty_] := UnitBox[Mod[t/period, 1.]/(2. duty)];
pwm1[t_] := rectangleWave[t, period, dc1];
pwm2[t_] := rectangleWave[t, period, dc2];
pwm[t_, tsplit_] := Piecewise[{{pwm1[t], t < tsplit}, {pwm2[t], t >= tsplit}}];
step[t_, tstep_, dc1_, dc2_] := dc1 + (dc2 - dc1) UnitStep[t - tstep];

(* ripple functions *)
Clear[ripple, v1, v2, duty, t0, rc1];
r = Solve[{v1 + (1 - v1) (1 - E^(-duty t0/rc1)) == v2 &&
v2 E^(-(1 - duty) t0/rc1) == v1 && ripple == v2 - v1}, {v1, v2, ripple}];
ripplemin[t0_, rc1_, duty_] = First[v1 /. r];
ripplemax[t0_, rc1_, duty_] = First[v2 /. r];
rippleampl[t0_, rc1_, duty_] = First[ripple /. r];
y0 = ripplemin[period, rc, dc1];

(* main function *)
ss = NDSolve[{rc  y'[t] + y[t] == step[t, tsplit, dc1, dc2], y == dc1},
y, {t, mint, maxt}];
s = NDSolve[{rc  y'[t] + y[t] == pwm[t, tsplit], y[mint] == y0},
y, {t, mint, maxt}, MaxStepSize -> 0.05];

(* find end ripple *)
ripple = rippleampl[period, rc, dc2]; NumberForm[ripple, {3, 3}]
rpmin = ripplemin[period, rc, dc2];
rpmax = ripplemax[period, rc, dc2];

(* Plot *)
Plot[{pwm[t, tsplit], Evaluate[y[t] /. s], step[t, tsplit, dc1, dc2],
Evaluate[y[t] /. ss]}, {t, mint, maxt}, Exclusions -> None,
ImageSize -> {480, 300}, PlotRange -> All, PlotPoints -> 1000,
PlotStyle -> {Automatic, Automatic, Thick}, Axes -> {True, False},
PlotRangeClipping -> False,
Epilog -> {{Table[{Dotted, Line[{{mint, i}, { maxt, i}}]}, {i, 0, 1, 0.2}]},
{Dashed, Line[{{maxt2, rpmin}, {2 maxt, rpmin}}]},
{Dashed, Line[{{maxt2, rpmax}, {2 maxt, rpmax}}]},
{Text[NumberForm[ripple, {3, 3}], {maxt + 1, dc2}]},
{Arrow[{{maxt + 0.1, rpmax + 0.1}, {maxt + 0.1, rpmax}}]},
{Arrow[{{maxt + 0.1, rpmin - 0.1}, {maxt + 0.1, rpmin}}]} }]

• Try ImagePadding -> All, or setting the ImagePadding directly. – rcollyer Aug 12 '12 at 13:04
• @rcollyer - Doesn't work with All, but does with a numerica value. Thanks. – stevenvh Aug 12 '12 at 13:14

## 3 Answers

rcollyer gave me the right "magic word": ImagePadding does the trick. I tried

ImagePadding -> All


like he suggested, but for some reason that doesn't work. With explicit values:

ImagePadding -> {{0, 20}, {0, 0}}


it works OK. Parameters are left, right, bottom and top padding, resp.

Note that this still needs PlotRangeClipping to be False.

Thanks, rcollyer.

edit
I didn't notice it first, but with bottom padding set to 0 the bottom half of the x-axis labels is cut off: Bug? Anyway, fixed by setting the value to 5 Simon hints to use All as parameters, which is much better than the random 5 I used. Thanks, Simon.

ImagePadding -> {{All, 20}, {All, All}} • There's a line in the movie Labyrinth, "say the right words," and sometimes it is exactly like that! :) – rcollyer Aug 12 '12 at 14:21
• – Dr. belisarius Aug 12 '12 at 16:29
• @Verde - I entered "Friend" and MMA said "Friend" back. Isn't that sweet? :-) – stevenvh Aug 13 '12 at 13:59
• @stevenvh Yeah, but never try a four letters word – Dr. belisarius Aug 13 '12 at 14:16
• @stevenvh, you can use All for the individual elements to ensure sufficient space for the labels: ImagePadding -> {{All, 20}, {All, All}} – Simon Woods Aug 15 '12 at 12:22

I would rather draw those Epilog things in a separate Graphics then combine them by Show:

mainplot =
Plot[{pwm[t, tsplit], Evaluate[y[t] /. s], step[t, tsplit, dc1, dc2],
Evaluate[y[t] /. ss]}, {t, mint, maxt}, Exclusions -> None,
ImageSize -> {480, 300}, PlotRange -> All, PlotPoints -> 1000,
PlotStyle -> {Automatic, Automatic, Thick}, Axes -> {True, False}]

epilogplot =
Graphics[{{Table[{Dotted, Line[{{mint, i}, {maxt, i}}]}, {i, 0, 1, 0.2}]}, {Dashed,
Line[{{maxt2, rpmin}, {1.04 maxt, rpmin}}]}, {Dashed,
Line[{{maxt2, rpmax}, {1.04 maxt, rpmax}}]}, {Text[
NumberForm[ripple, {3, 3}], {maxt + 1,
dc2}]}, {Arrow[{{maxt + 0.1, rpmax + 0.1}, {maxt + 0.1,
rpmax}}]}, {Arrow[{{maxt + 0.1, rpmin - 0.1}, {maxt + 0.1,
rpmin}}]}}]

Show[{mainplot, epilogplot}] The PlotRange -> All setting in mainplot will ensure all contents in mainplot and epilogplot not being clipped when they are combined in Show.

Another possibility is PlotRangePadding.

Plot[{pwm[t, tsplit], Evaluate[y[t] /. s], step[t, tsplit, dc1, dc2],
Evaluate[y[t] /. ss]}, {t, mint, maxt}, Exclusions -> None,
ImageSize -> {480, 300}, PlotRange -> All, PlotPoints -> 1000,
PlotStyle -> {Automatic, Automatic, Thick}, Axes -> {True, False},
PlotRangeClipping -> False,

PlotRangePadding -> {2, 0.05},

Epilog -> {{Table[{Dotted, Line[{{mint, i}, {maxt, i}}]}, {i, 0, 1,
0.2}]}, {Dashed,
Line[{{maxt2, rpmin}, {2 maxt, rpmin}}]}, {Dashed,
Line[{{maxt2, rpmax}, {2 maxt, rpmax}}]}, {Text[
NumberForm[ripple, {3, 3}], {maxt + 1,
dc2}]}, {Arrow[{{maxt + 0.1, rpmax + 0.1}, {maxt + 0.1,
rpmax}}]}, {Arrow[{{maxt + 0.1, rpmin - 0.1}, {maxt + 0.1,
rpmin}}]}}] • My only issue with PlotRangePadding is that it extends the axes, too. But, it works, so +1. – rcollyer Aug 12 '12 at 14:19