2
$\begingroup$

I'd like to plot

Abs[s]/λ - 1 + Log[λ/s]

as a function of $s > 0$, for some fixed value for $\lambda$, say 0.1. This function behaves essentially linearly for $s > \lambda$, and the log-linear plot is linear for $s < \lambda$. It would therefore be nice to see the plot from $s=e^{-8}$ to $s=8$. There should be roughly the same number of ticks on both sides, if I'm not mistaken.

I'd like to depict this by having a plot that is log linear to the left of $\lambda$, and linear to the right of $\lambda$. Any advice?

$\endgroup$
2
  • 1
    $\begingroup$ Your function assumes complex values for $\lambda=0.1$ and $s<0$. Could you check your expressions? $\endgroup$
    – MarcoB
    May 25, 2018 at 14:37
  • $\begingroup$ s must be nonnegative. I've fixed the associated typo. $\endgroup$ May 26, 2018 at 1:04

3 Answers 3

2
$\begingroup$

Using the scaling functions {f[λ], if[λ]} from Brett's excellent answer and adding a few embellishments:

Quiet[With[{λ = 0.3}, 
 {lscale, rscale} = Thread[{0,  NMaxValue[{Abs[s]/λ - 1 + Log[λ/s] , #}, s] & /@ 
   {10^(-4) <= s <= λ , λ <= s <= 8}}];
 plot = Plot[If[s < λ, Abs[s]/λ - 1 + Log[λ/s], 
       Rescale[Abs[s]/λ - 1 + Log[λ/s], rscale, lscale ]], {s, 10^-4, 8}, 
    ScalingFunctions -> {{f[λ], if[λ]}, None}, 
    Frame -> True, 
    FrameTicks -> {{Automatic,  Charting`FindTicks[lscale, rscale]}, {All, All}}, 
    Mesh -> {{λ}}, MeshShading -> {Red, Blue}, 
    FrameStyle -> {{Red, Blue}, {Automatic, Automatic}}];
 ticks = FrameTicks /. Options[plot, FrameTicks];
 ticks[[2, 1]] = Join[ticks[[2, 1]], {λ, λ}, {#, #} & /@ Range[8]]; 
 ticks[[2, 2]] = ticks[[2, 1]];
 Show[plot, FrameTicks -> ticks, ImageSize -> 500]]]

enter image description here

$\endgroup$
2
$\begingroup$

Here's my attempt, using ScalingFunctions.

The first step is to define a function (and it's inverse) that is linear for inputs greater than $\lambda$, and is log-scaled for input below, with a shift so that we preserve continuity:

f[λ_][a_] := If[a < λ, Log[a] + λ - Log[λ], a]
if[λ_][a_] := If[a < λ, E^(-λ + a) λ, a]

Just for fun, I've included λ as a parameter to the scaling functions.

Now we just plot as usual:

With[{λ = 0.1}, 
     Plot[Abs[s]/λ - 1 + Log[λ/s], {s, 10^-4, 8}, 
          ScalingFunctions -> {{f[λ], if[λ]}, None}
     ]
] // VisualQuiet

enter image description here


The ticks aren't perhaps what you'd want, since in this case Plot decided to go for powers of 10 across the domain; that could be changed with a custom Ticks specification.

Also, at least in V11.3, the graphic pinks because of some apparently benign recursion error I haven't debugged yet, so I'm throwing in a utility I have for telling the frontend to not turn the graphic pink if there are errors:

VisualQuiet[expr_] := Style[expr, AutoStyleOptions -> {
    "FormattingErrorTooltips" -> False, 
    "HighlightFormattingErrors" -> False
}]
$\endgroup$
1
$\begingroup$

It is hard to see how to improve on side-by-side plots:

With[{λ = 0.1}, GraphicsRow@{
   LogLinearPlot[Abs[s]/λ - 1 + Log[λ/s], {s, Exp[-8], λ}],
   Plot[Abs[s]/λ - 1 + Log[λ/s], {s, λ, 8}]
   }]
$\endgroup$
2
  • $\begingroup$ I'm now figuring out how to make the two graphs overlap so that I actually realize my goal. $\endgroup$ May 26, 2018 at 1:06
  • $\begingroup$ The solution of @kglr gives you that (and elegantly), but we usually plot for communication, and I suspect communication will be much more rapid with side-by-side separate plots. (E.g., ask why color is needed to make the combined plot comprehensible.) $\endgroup$
    – Alan
    May 26, 2018 at 13:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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