18
$\begingroup$

I want to programmatically draw some objects outside the Plot area in my Plot's Epilog, like in this dummy:

enter image description here

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:

enter image description here

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[0] == 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}}]} }]
$\endgroup$
2
  • 3
    $\begingroup$ Try ImagePadding -> All, or setting the ImagePadding directly. $\endgroup$
    – rcollyer
    Commented Aug 12, 2012 at 13:04
  • $\begingroup$ @rcollyer - Doesn't work with All, but does with a numerica value. Thanks. $\endgroup$
    – stevenvh
    Commented Aug 12, 2012 at 13:14

3 Answers 3

16
$\begingroup$

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:

enter image description here

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}}

enter image description here

$\endgroup$
9
  • $\begingroup$ There's a line in the movie Labyrinth, "say the right words," and sometimes it is exactly like that! :) $\endgroup$
    – rcollyer
    Commented Aug 12, 2012 at 14:21
  • $\begingroup$ @rcollyer bellsouthpwp.net/d/p/dptolar/friend.htm $\endgroup$ Commented Aug 12, 2012 at 16:29
  • $\begingroup$ @Verde - I entered "Friend" and MMA said "Friend" back. Isn't that sweet? :-) $\endgroup$
    – stevenvh
    Commented Aug 13, 2012 at 13:59
  • 1
    $\begingroup$ @stevenvh Yeah, but never try a four letters word $\endgroup$ Commented Aug 13, 2012 at 14:16
  • 3
    $\begingroup$ @stevenvh, you can use All for the individual elements to ensure sufficient space for the labels: ImagePadding -> {{All, 20}, {All, All}} $\endgroup$ Commented Aug 15, 2012 at 12:22
8
$\begingroup$

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}}]}}]

enter image description here

$\endgroup$
1
  • 3
    $\begingroup$ My only issue with PlotRangePadding is that it extends the axes, too. But, it works, so +1. $\endgroup$
    – rcollyer
    Commented Aug 12, 2012 at 14:19
8
$\begingroup$

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}]

Mathematica graphics

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

$\endgroup$

Your Answer

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

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