5
$\begingroup$

I would like to accurately distort this plot of $\sin(x^{1/2})$ (and others like it) so that the wavelengths are evened out (ie - "inverse-square root" it).

enter image description here

I should like to do the same to "de-log" plots too.

I have no idea where to start though.

$\endgroup$
5
  • $\begingroup$ Well, if $f(x) = \sin(x^2)$, you could just plot $f(\sqrt x)$ instead? Pretty sure what you have there's not a plot of $\sin(x^2)$ though. $\endgroup$
    – user484
    Commented Sep 14, 2014 at 1:34
  • $\begingroup$ Yes, sin(x^2) should be zero at the origin. $\endgroup$ Commented Sep 14, 2014 at 1:54
  • $\begingroup$ Sorry - corrected. I would like to distort images with this proportion - the plot was just an eg $\endgroup$
    – martin
    Commented Sep 14, 2014 at 2:27
  • 1
    $\begingroup$ There are lots of ways to do this, but you probably need to be more specific. The words "accurate" and "distort" seem to be at odds. One way would be Sin[Sqrt[x]] /. x -> x^2/1000. Another, if you want to "morph" the graphs would be (1 - t) Sqrt[x] + t x / Sqrt[1000], for t running from 0 to 1. That's assuming x ranges from 0 to 1000. $\endgroup$
    – Michael E2
    Commented Sep 14, 2014 at 2:45
  • $\begingroup$ It is images really that I would like to distort - including the axes etc. I shall probably have to reword it in the morning! $\endgroup$
    – martin
    Commented Sep 14, 2014 at 2:55

3 Answers 3

6
$\begingroup$
plt1 = Plot[Sin[Sqrt[x]], {x, 0, 1000}, ImageSize -> 400];

ticks = Ticks /. AbsoluteOptions[plt1, Ticks];
ticks = MapAt[#^(1/2) &, ticks, {{1, All, 1}}];
plotrange = PlotRange[plt1];
plotrange = MapAt[#^(1/2) &, plotrange, {1}]; 

plt2 = Graphics[plt1[[1]] /. Line[x_] :> Line[{#[[1]]^(1/2), #[[2]]} & /@ x], 
                PlotRange -> plotrange, Ticks -> ticks, plt1[[2]]];
Row[{plt1, plt2}]

enter image description here

Update: The approach above works without issue in Version 9.0.1.0 (Windows 8 64bit). Unfortunately it does not work in Version 10 because AbsoluteOptions stopped working as expected in Version 10. A work-around until the AbsoluteOptions glitch is fixed (hopefully in Version 10.0.1.0) is to specify the ticks directly:

ticksb = {{#^(1/2),#}&/@FindDivisions[{0,1000},{5}][[1]],Automatic};
plt2b = Graphics[plt1[[1]] /. Line[x_] :> Line[{#[[1]]^(1/2), #[[2]]} & /@ x], 
            PlotRange -> plotrange, Ticks -> ticksb, plt1[[2]]];
Row[{plt1, plt2b}]

enter image description here

$\endgroup$
9
  • $\begingroup$ brilliant! Thank you! $\endgroup$
    – martin
    Commented Sep 14, 2014 at 8:31
  • $\begingroup$ I am getting the following errors ... any ideas? Axes::axes: {{False,False},{False,False}} is not a valid axis specification. >>`` Axes::axes: {{False,False},{False,False}} is not a valid axis specification. >>`` Ticks::ticks: {Automatic,Automatic} is not a valid tick specification. >>`` Ticks::ticks: {Automatic,Automatic} is not a valid tick specification. >>`` Axes::axes: {{False,False},{False,False}} is not a valid axis specification. >>`` General::stop: Further output of Axes::axes will be suppressed during this calculation. >> $\endgroup$
    – martin
    Commented Sep 14, 2014 at 8:35
  • $\begingroup$ do I need to load a package? $\endgroup$
    – martin
    Commented Sep 14, 2014 at 9:43
  • $\begingroup$ @martin, this works without issue with in 9.0.1.0 (Windows 8 64bit). Just confirmed that it does not work in Version 10 because AbsoluteOptions stopped working es expected in Version 10. I will try to find a workaround to handle the ticks. (The rest of the code works if you you comment out the parts involving ticks) $\endgroup$
    – kglr
    Commented Sep 14, 2014 at 10:05
  • 1
    $\begingroup$ @Martin, I think Log[0] (Indeterminate) in ticksb and plotrange is the source of the problem. You can either (1) change the range {0,1000} to {1,1000} or (2) use ticksb /. Indeterminate->0 instead of ticksb and similarly for plotrange. $\endgroup$
    – kglr
    Commented Sep 14, 2014 at 14:09
3
$\begingroup$

Here is an attempt to do this using the internal options used by LogPlot etc. It has the advantage of correctly working with the adaptive sampling of Plot to produce a better result with extreme scaling.

SetAttributes[scaledPlot, HoldRest]

scaledPlot[scfn_, exp_, {s_, r1_, r2_}, arg___] :=
 With[{inv = InverseFunction[scfn]},
   Plot[exp, {s, scfn[r1], scfn[r2]}, arg, 
     Method -> {"MappingFunctions" -> {{#1, #2} &, {#1, #2} &}, 
                "DomainMappingFunctions" -> {inv}},
     Ticks -> {Charting`ScaledTicks[{scfn, inv}], Automatic}
   ]
 ]

Examples:

scaledPlot[Sqrt, Sin[x^(1/2)], {x, 0, 1000}]

enter image description here

scaledPlot[#^(1/4) &, Sin[x^(1/4)], {x, 0, 2*^6}]

enter image description here

Compare the second result with the same plot using kguler's method and the value of adaptive sampling becomes apparent:

plt1 = Plot[Sin[x^(1/4)], {x, 0, 2*^6}, ImageSize -> 400];
ticksb = {{#^(1/4), #} & /@ FindDivisions[{0, 2*^6}, {5}][[1]], Automatic};
plt2b = Graphics[plt1[[1]] /. Line[x_] :> Line[{#[[1]]^(1/4), #[[2]]} & /@ x], 
  PlotRange -> plotrange, Ticks -> ticksb, plt1[[2]]]

enter image description here

The more extreme the scaling the worse this problem will become, and adding PlotPoints will not overcome it. (e.g. try x^(1/9))

Note: Sometimes the tick marks disappear, e.g. with #^(1/3) &. This seems like a problem with Charting`ScaledTicks but one can always specify a list of ticks manually if necessary.

$\endgroup$
4
  • $\begingroup$ this is really great - should have waited before accepting :/ Thank you! $\endgroup$
    – martin
    Commented Sep 14, 2014 at 14:09
  • $\begingroup$ Is it possible to use this with ListLinePlot? $\endgroup$
    – martin
    Commented Sep 14, 2014 at 14:13
  • 1
    $\begingroup$ @martin (1) Thanks. (2) Yes, I recommend waiting a bit longer before Accepting an answer. However, if you feel so inclined you can change (or remove) your Accept at any time. (3) I don't believe these Method options apply to ListLinePlot, but since you wouldn't get adaptive sampling there anyway a manual scaling approach seems reasonable. $\endgroup$
    – Mr.Wizard
    Commented Sep 14, 2014 at 14:25
  • $\begingroup$ Thanks for the advice - really great answer - I feel a bit mean unaccepting an answer though ... :/ $\endgroup$
    – martin
    Commented Sep 14, 2014 at 14:35
0
$\begingroup$

Based on your last comment and if I understand it correctly, you want to work with the image itself. If so, maybe something like this would help.

img = Plot[Sin[Sqrt[x]], {x, 0, 1000}];

 ImageTransformation[img, {#[[1]]^2, #[[2]]} &]
$\endgroup$
2
  • $\begingroup$ I tried it, expecting to point out that the tickmarks would look awful. They do. But actually, even the graph itself looks pretty ghastly. $\endgroup$
    – Igor Rivin
    Commented Sep 14, 2014 at 3:20
  • $\begingroup$ if he use PlotPoints -> 100 the plot could be better. $\endgroup$ Commented Sep 14, 2014 at 3:26

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.