Re: Re: condense axis
- To: mathgroup at smc.vnet.net
- Subject: [mg103325] Re: [mg103299] Re: condense axis
- From: "David Park" <djmpark at comcast.net>
- Date: Tue, 15 Sep 2009 04:26:20 -0400 (EDT)
- References: <23668144.1252713896870.JavaMail.root@n11> <h8g0fd$bq3$1@smc.vnet.net> <19147537.1252928875558.JavaMail.root@n11>
Thanks Peter, that's very nice. But what if the two functions have vastly different scales? Is the following case acceptable? ySplitPlot[{1/10 Sin[x]^2, Cos[x]^2 + 10}, {x, 0, 2 Pi}, {1.5, 8}, ImageSize -> 250] Here are two Presentations solutions: Needs["Presentations`Master`"] f1[x_] := 1/10 Sin[x]^2 f2[x_] := 10 + Cos[x]^2 This is a simple solution that uses different scales on the left and right of the plot. The underlying y coordinate goes from 0 to 10. Function f1 is Rescaled to fit in the range 0.5<=y<=4.5 and f2 is Rescaled to fit in the range 5.5<=y<=9.5. f1ticks = CustomTicks[Rescale[#, {0, .1}, {0.5, 4.5}] &, {0, .1, .02, 2}, CTNumberFunction -> (If[# == 0, 0, NumberForm[#, {3, 2}]] &)]; f2ticks = CustomTicks[Rescale[#, {10, 11}, {5.5, 9.5}] &, {10, 11, .2, 2}, CTNumberFunction -> (NumberForm[#, {3, 1}] &)]; Draw2D[ {Draw[Rescale[f1[x], {0, .1}, {0.5, 4.5}], {x, 0, 2 \[Pi]}], Draw[Rescale[f2[x], {10, 11}, {5.5, 9.5}], {x, 0, 2 \[Pi]}], Text[Style["f1", 14], {2.505, 3.394}], Text[Style["f2", 14], {4.092, 8.289}]}, AspectRatio -> 1, PlotRange -> {{0, 2 \[Pi]}, {0, 10}}, Frame -> True, FrameTicks -> {{f1ticks, f2ticks}, {Automatic, Automatic}}, ImageSize -> 250] The following solution uses XTickLine and two YTickLines to put both scales on the left side. Draw2D[ {Draw[Rescale[f1[x], {0, .1}, {0.5, 4.5}], {x, 0, 2 \[Pi]}], Draw[Rescale[f2[x], {10, 11}, {5.5, 9.5}], {x, 0, 2 \[Pi]}], Text[Style["f1", 14], {2.505, 3.394}], Text[Style["f2", 14], {4.092, 8.289}], XTickLine[{0, 2 \[Pi], .4}, {0, 2 \[Pi]}, {0, 2 \[Pi], 1}, 5], YTickLine[{.5, 4.5, 0}, {0, .1}, {0, .1, .02}, 2, YTextSpecs -> {{1, 0}, {1, 0}, 0.008}, YNumberFunction -> (If[# == 0, 0, NumberForm[#, {3, 2}]] &)], YTickLine[{5.5, 9.5, 0}, {10, 11}, {10, 11, .2}, 2, YTextSpecs -> {{1, 0}, {1, 0}, 0.008}, YNumberFunction -> (NumberForm[#, {3, 1}] &)], Text[Style["\[TildeTilde]", 14], {0, 5}]}, AspectRatio -> 1, PlotRange -> {{-0.5, 2 \[Pi]}, {-.2, 10}}, Frame -> None, ImageSize -> 250] However I used a divider or axis break on the y axis that might not be considered entirely satisfactory. I decided that we need a general XAxisBreak and YAxisBreak to fill these gaps. I therefore designed them and added them to the Presentations DrawingAxesAndGrids section. There have been enough queries on MathGroup to make this seem justifiable. These functions will appear in updates dated after 14 Sep 2009. Peter Lindsay at the University of St Andrews, School of Mathematics and Statistics ( http://www.mcs.st-and.ac.uk/ ) keep an archive of Presentations solutions to various MathGroup questions http://blackbook.mcs.st-and.ac.uk/~Peter/djmpark/html/ and a notebook and PDF file of the solutions should appear there within a few days. This also shows the new YAxisBreak solution. David Park djmpark at comcast.net http://home.comcast.net/~djmpark/ From: pfalloon [mailto:pfalloon at gmail.com] On Sep 12, 9:25 pm, "David Park" <djmp... at comcast.net> wrote: > There are probably ways to do this in regular Mathematica. One possibility > is to make two plots and align them in a Column. Leave the x-scale off the > top plot. Each plot would have its own y scale. The problem might be to get > the correct horizontal alignment of the two plots. It the top plot has > longer tick labels you may need to specify ImagePadding for both plots so > they take the same space. > > You may get other suggestions. > > What I would do is use the Presentations package ($50) from my web site. > There are two approaches I might use. > > 1) Put both functions in the same plot with an underlying y coordinate (0 to > 10 say) but use Rescale to adjust the space taken by each function. I assume > that the lower function might be magnified in its y coordinate. Then I would > use the CustomTicks command in the package to put the lower tick scale on > the left and the upper tick scale on the left. These could be specified so > they only gave tick marks in the appropriate y region for each function. > > 2) A second method is a little like what I described above. I would use > Inset to place two plots on the same "piece of paper" without using any tick > scales. That makes it easy to align them. Then I would use the package > functions XTickLine and YTickLine to put tick labels on the edges of the > Insets. That way, we could get both tick scales on the left. > > David Park > djmp... at comcast.nethttp://home.comcast.net/~djmpark/ > > From: David [mailto:david.b.rid... at gmail.com] > > Hello, > I would like to plot two functions on the same 2-D plot. One function > has low values of y and the other has high values of y, so the figure > is rather ugly. How can I crunch the axis with a zig-zag to condense > the figure? > Thank you, > David Hi David, Well, with all due respect, I wouldn't recommend paying $50 for a package unless it could do *exactly* what you needed. By the sounds of it, you'll end up fiddling around just as much as if you started from scratch in "regular" Mathematica, with the added frustration that the functionality you're working with probably isn't going to be as robust. I think what you're requesting, i.e. some kind of built-in support for graphs with split axes, is totally reasonable, and my guess (hope?) is that something along these lines will be added within the next couple of versions (judging by the giant strides that have been made in graphics functionality over the previous couple of versions). Still, it doesn't hurt to make noise about it so it's clear there's demand for it. I would add that we also need support for multiple stacked graphs which share horizontal or vertical axes. In the meantime, below is a simple implementation of a split axis plot that may be useful. With a little tweaking you should be able to get to behave exactly as you want. The idea is that you specify where you want the split to occur (ySplit), and what offset to apply to points above the split (splitOffset): i.e. for y > ySplit, we want to relabel it as y+splitOffset. So, in the example given below, we want y=2 to appear as y=10, so the offset is 8. This code works by first doing a regular plot in which the "upper" curve is shifted, then relabeling the corresponding y ticks. Limitations are: only works on y axis, only handles ticks on regular axes (not FrameTicks if you set Frame->True). Hope this helps! Cheers, Peter. ySplitPlot[{f1_,f2_}, {x_,xmin_,xmax_}, {ySplit_,splitOffset_}, opts___] := Module[{ticks, frameTicks, plt, absOpts, x0, y0, splitLines}, plt = Plot[Evaluate[{f1, f2-splitOffset}], {x,xmin,xmax}, opts]; absOpts = AbsoluteOptions[plt]; {x0,y0} = AxesOrigin /. absOpts; {ticks, frameTicks} = {Ticks, FrameTicks} /. absOpts; ticks[[2]] = ticks[[2]] /. { {y_Real /; y>ySplit, ylbl_Real, args___} :> {y, ylbl+splitOffset, args}, {y_Real /; y==ySplit, ylbl_Real, args___} :> Sequence@@{} }; splitLines = Graphics[{ Line[{{x0-0.1,ySplit-0.05+0.02},{x0+0.1,ySplit+0.05+0.02}}], Line[{{x0-0.1,ySplit-0.05-0.02},{x0+0.1,ySplit+0.05-0.02}}] }]; Show[plt, splitLines, Ticks->ticks] ] ySplitPlot[{Sin[x]^2,Cos[x]^2+10}, {x,0,2Pi}, {1.5, 8}]