Skip to main content

plotting - weird behavior of plot


Can someone provide an explanation for the following behavior?


I define a function:


a=2480.65;
n[x_] := (1/x^2)*1/(Exp[a/x] - 1);

Plot[n[y], {y, 100, 1000}]
Plot[n[a], {a, 100, 1000}]

The first plot generates this:


good fig


while the second one looks like this:


bad fig


Trivially the first one is correct as this should be a monotonically increasing function. Is it something in the order of evaluation? How can I be careful not to stumble upon this point in less easily verified cases?


I'm using MMA 9, with mac



Answer




Plot and Table and others "effectively use Block to localize variables." Let's first look at your definition of n:


Mathematica graphics


We can see that it depends on the (unevaluated!) global symbol a. That means when a changes its value, the function changes, too!


Block is used to temporarily change the value of a global variable. Observe the difference:


Block[{a = b}, n[a]]
(* 1/(b^2 (-1 + E)) *)

n[a]
(* 9.45746*10^-8 *)


In the first case, a is changed to b and then that is substituted for x in expression for n. So both a and x are changed to b. That makes the first code equivalent to


(1/b^2)*1/(Exp[b/b] - 1)

In the second code, it works as intended, since a retains its value of 2480.65.


The Plot command effectively evaluate the first code,


Block[{a = x}, n[a]]
(* 1/((-1 + E) x^2) *)

except it does it with numeric values substituted for x. So effectively you're plotting a constant over x^2.


To avoid it, you should avoid having your function definitions depend on global variables, whenever possible. If the global variable is not intended to be a fixed constant, then you should make it an explicit argument of the function. (Such as David Stork has shown while I've been typing.)



n[x_, a_] := 1/(x^2 (Exp[a/x] - 1));

This is what probably should be done 99% of the time.


Sometimes it is intended to be a constant. If it is in a package, then it should be in a private context; see Contexts and Packages. Sometimes I'm lazy or the code is temporary, and the constant is a number that appears in several places. In that case, I might use one of the following two ways. First:


Block[{x},
n[x_] = (1/x^2)*1/(Exp[a/x] - 1);
]

Mathematica graphics


Second:



With[{a = 2480.65`},
n[x_] := (1/x^2)*1/(Exp[a/x] - 1);
]

Mathematica graphics


In both cases, we can see that the value of a appears in the exponent. In the first case the use of Set (=) instead of SetDelayed (:=) causes the right-hand side to be evaluated before the definition is stored; that is how the value of a is inserted. In the second, the value is injected with With; this rewriting of the rule causes the formal parameter x to be renamed x$; see, for example, Variables in Pure Functions and Rules. This is to protect the definition from having a value inject for x in the pattern x_, which would break the definition.


Comments

Popular posts from this blog

plotting - Plot 4D data with color as 4th dimension

I have a list of 4D data (x position, y position, amplitude, wavelength). I want to plot x, y, and amplitude on a 3D plot and have the color of the points correspond to the wavelength. I have seen many examples using functions to define color but my wavelength cannot be expressed by an analytic function. Is there a simple way to do this? Answer Here a another possible way to visualize 4D data: data = Flatten[Table[{x, y, x^2 + y^2, Sin[x - y]}, {x, -Pi, Pi,Pi/10}, {y,-Pi,Pi, Pi/10}], 1]; You can use the function Point along with VertexColors . Now the points are places using the first three elements and the color is determined by the fourth. In this case I used Hue, but you can use whatever you prefer. Graphics3D[ Point[data[[All, 1 ;; 3]], VertexColors -> Hue /@ data[[All, 4]]], Axes -> True, BoxRatios -> {1, 1, 1/GoldenRatio}]

plotting - Filling between two spheres in SphericalPlot3D

Manipulate[ SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, Mesh -> None, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], {n, 0, 1}] I cant' seem to be able to make a filling between two spheres. I've already tried the obvious Filling -> {1 -> {2}} but Mathematica doesn't seem to like that option. Is there any easy way around this or ... Answer There is no built-in filling in SphericalPlot3D . One option is to use ParametricPlot3D to draw the surfaces between the two shells: Manipulate[ Show[SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], ParametricPlot3D[{ r {Sin[t] Cos[1.5 Pi], Sin[t] Sin[1.5 Pi], Cos[t]}, r {Sin[t] Cos[0 Pi], Sin[t] Sin[0 Pi], Cos[t]}}, {r, 1, 2 - n}, {t, 0, Pi}, PlotStyle -> Yellow, Mesh -> {2, 15}]], {n, 0, 1}]

plotting - Mathematica: 3D plot based on combined 2D graphs

I have several sigmoidal fits to 3 different datasets, with mean fit predictions plus the 95% confidence limits (not symmetrical around the mean) and the actual data. I would now like to show these different 2D plots projected in 3D as in but then using proper perspective. In the link here they give some solutions to combine the plots using isometric perspective, but I would like to use proper 3 point perspective. Any thoughts? Also any way to show the mean points per time point for each series plus or minus the standard error on the mean would be cool too, either using points+vertical bars, or using spheres plus tubes. Below are some test data and the fit function I am using. Note that I am working on a logit(proportion) scale and that the final vertical scale is Log10(percentage). (* some test data *) data = Table[Null, {i, 4}]; data[[1]] = {{1, -5.8}, {2, -5.4}, {3, -0.8}, {4, -0.2}, {5, 4.6}, {1, -6.4}, {2, -5.6}, {3, -0.7}, {4, 0.04}, {5, 1.0}, {1, -6.8}, {2, -4.7}, {3, -1....