MathGroup Archive 2009

[Date Index] [Thread Index] [Author Index]

Search the Archive

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




  • Prev by Date: Re: Re: condense axis
  • Next by Date: Re: Bizarre error when exporting to PDF
  • Previous by thread: Re: Re: Re: condense axis
  • Next by thread: Re: Re: condense axis