Re: Plot axis length and size ratio (TwoPlot revive)
- To: mathgroup at smc.vnet.net
- Subject: [mg121635] Re: Plot axis length and size ratio (TwoPlot revive)
- From: matyigtm <matyigtm at gmail.com>
- Date: Fri, 23 Sep 2011 03:43:47 -0400 (EDT)
- Delivered-to: l-mathgroup@mail-archive0.wolfram.com
- References: <j5cb27$crg$1@smc.vnet.net>
Thanks for the ideas. I've already found the TwoAxisPlot version, but I didn't like that it had to plot three times the diagrams in total, which is time consuming in my occasion. In Ray's version, which short enough to be usable, its hard to guess the scale factor if I need to make several "two plots" in loops (hundreds of plots), which motivates me to make a function that retains most of the Plot function's parameters, options. Upon your ideas I've created: Options[TwoPlot] = {PlotOptions1 -> {}, PlotOptions2 -> {}, PlotOptionsAll -> {}, PlotOptionsFrame -> {}, PlotFcn -> Plot, Scale -> Automatic}; TwoPlot[{f_, g_}, {x_, xmin_, xmax_}, opts : OptionsPattern[{TwoPlot, Graphics}]] := Module[{plt1, plt2, absOpt1, absOpt2, absOptTmp, fcnTmp, lenF, lenG, a, b, range1, range2, rangeDst, scale, ticks2, base = 0}, (* number of elements in f and g *) {lenF, lenG} = (If[ListQ[#], Length[#], 1] &) /@ {f, g}; plt1 = (OptionValue@PlotFcn)[f, {x, xmin, xmax}, Evaluate@OptionValue@PlotOptions1, Evaluate@OptionValue@PlotOptionsAll]; absOpt1 = AbsoluteOptions[plt1]; plt2 = (OptionValue@PlotFcn)[g, {x, xmin, xmax}, Evaluate@OptionValue@PlotOptions2, Evaluate@OptionValue@PlotOptionsAll, PlotStyle -> ColorData[1, "ColorList"][[lenF + 1 ;; lenF + lenG]]]; absOpt2 = AbsoluteOptions[plt2]; (* scale factor *) range1 = PlotRange /. absOpt1; range2 = PlotRange /. absOpt2; If[TrueQ[OptionValue@Scale == Automatic], (*then*) scale = Min[ Table[If[range2[[2, i]] != 0., range1[[2, i]]/ range2[[2, i]], \[Infinity]], {i, 1, 2}]], (* else *) scale = OptionValue@Scale]; rangeDst = Table[({Min, Max}[[i]])@{range1[[2, i]], range2[[2, i]] scale}, {i, 1, 2}]; (* creates internal plot to create new ticks for plot nr .2 *) a = (rangeDst[[2]] /scale - rangeDst[[1]]/ scale)/(xmax - xmin); fcnTmp = a x + (rangeDst[[1]]/ scale - a xmin); absOptTmp = AbsoluteOptions[(OptionValue@PlotFcn)[fcnTmp, {x, xmin, xmax}, PlotRange -> {All, rangeDst/ scale}, PlotPoints -> 2, MaxRecursion -> 0, Evaluate@OptionValue@PlotOptions2, Evaluate@OptionValue@PlotOptionsAll]]; (* rescale the ticks *) ticks2 = (Ticks /. absOptTmp)[[ 2]] /. {v_, label_, len_, style_} -> {v scale , label, len, style}; (* create the overlaid plots *) Graphics[{Drop[plt1[[1, 1]], 2], Scale[Drop[plt2[[1, 1]], 2], {1, scale}, {xmin, base}]}, FilterRules[{opts}, Options[Graphics]], AspectRatio -> (AspectRatio /. absOpt1), Frame -> True, FrameTicks -> {{Automatic, ticks2}, {All, Automatic}}, FrameStyle -> {{(AxesStyle /. absOpt1)[[ 2]], (AxesStyle /. absOpt2)[[2]]}, {(AxesStyle /. absOpt1)[[ 1]], Automatic}}, PlotRange -> {Automatic, rangeDst}] ]; SetAttributes[TwoPlot, HoldAll]; which applies in different manners: TwoPlot[{x (x - 10) Sin[x], 10 x (x - 10) Cos[x]}, {x, 0, 10}] TwoPlot[{{x (x - 10) Sin[x], 20 Cos[x]}, 10 x (x - 10) Cos[x]}, {x, 0, 10}, FrameLabel -> {{"y1", "y2"}, {, }}] I thought that an easy conversion to functions LogPlot,LogLinearPlot etc.. would be easy, but I found that not. I should convert the ticks accordingly to the Plot function used: TwoPlot[{{x (x - 10) Sin[x], 20 Cos[x]}, 10 x (x - 10) Cos[x]}, {x, 1, 10}, FrameLabel -> {{"y1", "y2"}, {, }}, PlotFcn -> LogPlot] Matyi