0
$\begingroup$

There has got to be some better way of plotting near vertical function values other than the default 2D Mesh. The only specifications that I want to give are the function definition and the horizontal and vertical ranges and have Mathematica figure out the appropriate mesh type, mesh points, and display. Shown below is the problem with a default function display, which generates lots of mesh points, but too few in the nearly singular areas, and one solution to this, which is a bit tedious. Note, this is a general mesh problem for all 2D plots; log, log-log, loglinear, and linear. enter image description here

As can be seen on the left panel, the mesh values become more frequent as the slope magnitude increases, and even become bizarre on the right hand of that plot (probably complex valued errors), simple procedures like increasing MaxRecursion -> 15, PlotPoints -> 10000, only marginally improve the plot. Note that the left panel default plot does not even vaguely follow the extreme y-axis values of the plot.

To improve the plot, one finds equal increment $y$-axis values by using FindRoot to solve for $x=f^{-1}[y]$. Then, equal interval $x$-axis values are found for $y=f[x]$. Finally, the two "mesh" tables are joined and sorted for increasing $x$-coordinate values using the command tab = Sort[Join[tab1, tab2], #1[[1]] < #2[[1]] &]; and the result plotted as the improved plot in the right-hand panel above.

Here is the code:

$MinPrecision = 30; y =.;
a = 0.5`30; b = 0.01`30;(*y=f[x] parameters*)
y = SetPrecision[(a b^a x^(-1 + a) (Sqrt[\[Pi]] - 2 b x))/Gamma[(1 + a)/2], 30];(*y=f[x]*)

(*Create 22 new mesh points, first at equal log intervals on the y-axis*)
tab1 = Table[
 Flatten[{FindRoot[10^n == y, {x, 10^-n}, 
   WorkingPrecision -> 30][[All, 2]], 10^n}], {n, -13, 8, 1}];

(*Create 22 mesh points at equal x-axis intervals*)
tab2 = Table[{x, y}, {x, 2, 86, 4}];

(*Join the mesh points and sort by increasing x-values, remove ";" to examine*)
tab = Sort[Join[tab1, tab2], #1[[1]] < #2[[1]] &];

(*Output results*)
Print["\t\t\t\t\t\t New Mesh Length of ", Length[tab1], " (tab1) + ", 
 Length[tab2], " (tab2) = ", Length[tab], " (tab total)"]

(*Default LogPlot y=f[x], then ListLogPlot properly*)
Print[
 LogPlot[y, {x, 0, 100}, ImageSize -> Medium, 
  PlotRange -> {{-10, 100}, {1/10000000000000, 100000000}}, 
  AxesOrigin -> {-10, 10^-13}, Mesh -> All, 
  MeshStyle -> Directive[PointSize[0.01], Red], 
  PlotLabel -> "Default log plot"], 
 ListLogPlot[tab, 
  PlotRange -> {{-10, 100}, {1/10000000000000, 100000000}}, 
  ImageSize -> Medium, Joined -> True, AxesOrigin -> {-10, 10^-13}, 
  Mesh -> All, MeshStyle -> Directive[PointSize[0.01], Red], 
  PlotLabel -> "Improved plot: listlog type"]]

How can this type of plot be performed a bit less tediously than as I have done it above?

$\endgroup$
10
  • $\begingroup$ I think you need to look at your problem at different angle. Plot or LogPlot already have the desired functionality. Why not simply use them instead of inventing own meshing procedure? $\endgroup$
    – yarchik
    Commented Apr 15 at 20:18
  • $\begingroup$ @yarchik Really? Well, I have tried, and I put my money where my mouth is and found a solution. I am asking for exactly what you said, that is, to find a Plot or LogPlot display that actually solves the problem rather than doing what I did. Try it yourself if you do not believe me, or alternatively show me what I asked for. $\endgroup$
    – Carl
    Commented Apr 15 at 20:25
  • $\begingroup$ @yarchik To put it another way, the default method of finding mesh points or mesh functions doesn't work for nearly vertical lines. If you know of some way of creating better mesh functions within a Plot routine, then show me because it is not at all obvious to me, and I am at my wits end looking for it. $\endgroup$
    – Carl
    Commented Apr 15 at 20:35
  • $\begingroup$ @yarchik It may be a bug, so is it bug or not? $\endgroup$
    – Carl
    Commented Apr 15 at 20:43
  • $\begingroup$ Wouldn't you want more points where the curve is changing rapidly? You can try PlotPoints -> 100, MaxRecursion -> 15 to get more points. $\endgroup$
    – MelaGo
    Commented Apr 15 at 21:19

2 Answers 2

1
$\begingroup$

The objective seem purely visual as opposed to needing the ability to discern both an x and a y value from the figure. If so, why not just pick values for 2 line segments to fill in the gaps.

(* Pick 2 sets of 2 values of y points to join *)
ylower = {10^(-10), 10^(-7)};
yupper = {10, 10^10};

(* Find corresponding x values *)
upper = Flatten[{x, y} /. Solve[y == #, x] & /@ yupper, 1];
lower = Flatten[{x, y} /. Solve[y == #, x] & /@ ylower, 1];

(* Show results *)
Show[LogPlot[y, {x, 0, 100},
  PlotRange -> {{-10, 100}, {ymin, ymax}},
  AxesOrigin -> {-10, ylower[[1]]},
  PlotRangeClipping -> False],
 ListLogPlot[lower, Joined -> True],
 ListLogPlot[upper, Joined -> True]]

Plot of function with desired vertical range

$\endgroup$
3
  • $\begingroup$ Please don't trivialize the problem. I want an actual solution that runs faster and more economically, for which I do not have to manually find asymptotes just to plot a function. The current default assigns too many $y=f(x)$ mesh points and appears to assign more mesh points for high curvature regions, which is inferior to solving for equal ArcLength intervals, or assigning $y=f(x)$ as well as $x=f^{-1}(y)$ mesh coordinates. I have a lot of curves with the same problem, and I don't know ahead of time where the vertical asymptotes are or even if there are any. Got something? PS, how are you? $\endgroup$
    – Carl
    Commented Apr 16 at 1:07
  • $\begingroup$ I'm doing well thanks. It appears you haven't changed much in that one needs to give more thought to your questions. $\endgroup$
    – JimB
    Commented Apr 16 at 4:18
  • $\begingroup$ OK, (+1) for effort, but I need a more general mesh for display. $\endgroup$
    – Carl
    Commented Apr 16 at 18:24
0
$\begingroup$

Thinking about this more I have a (somewhat sarcastic) solution to the problem that requires minimal input. The problem is that you don't specify the vertical limits and Mathematica doesn't use the same values that you would use.

You have chosen the minimum and maximum $x$ values as -10 and +100. The maximum value of $y$ when $x\to 0$ is $\infty$ which even on a log scale can't be shown on finite-sized monitors. So Mathematica picks a value that different from what you have in mind. When $x=100$, then $y \approx -0.000928444$ which also doesn't work well on a log scale for a vertical axis.

When Mathematica plots the function, it (apparently) has a non-None value for PlotRangePadding. If we add in PlotRangePadding -> None, then everything looks fine (i.e., no gaps):

a = 1/2; b = 1/100;
y = (a  b^a  x^(-1 + a)  (Sqrt[\[Pi]] - 2  b  x))/Gamma[(1 + a)/2]
LogPlot[y, {x, -10, 100}, PlotRangePadding -> None]

If you want a different set of vertical limits, you'll have to tell Mathematica what you want. In short, only giving the horizontal limits means that Mathematica can't guess what you have in mind (until the Personalized AI version becomes available early next year).

Curve with PlotRangePadding -> None

$\endgroup$
3
  • $\begingroup$ Yes but that is not the range I needed because of other considerations, and which plot range I specified. What you are showing is not different than the left hand panel in my question. And it is not me that cannot scale things properly, but rather the software which cannot because it doesn't scale properly. Best wishes, and you usually give me a run for my money despite the fact that I don't try to ask trick questions. $\endgroup$
    – Carl
    Commented Apr 16 at 11:07
  • $\begingroup$ I know it's not the range you needed. That's the whole point of my answer. Your question definition is missing the vertical range you have in mind. You complain in the first two paragraphs that Mathematica doesn't do what is in your head without mentioning your desired vertical range. It is only in your code that the desired vertical range appears. Finally, you ask about how to do what you did less tediously. Is the only specification that you want to give the function definition and the horizontal and vertical ranges and have Mathematica figure out the rest? If so, make it explicit. $\endgroup$
    – JimB
    Commented Apr 16 at 13:16
  • $\begingroup$ Done as requested, in bold. $\endgroup$
    – Carl
    Commented Apr 16 at 18:21

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.