ColorFunctionScaling example from Mathematica help fails - why? - wolfram-mathematica

There is an example in the Mathematica 7 help for Plot > Options > ColorFunctionScaling.
Table[Plot[Sin[4 Pi x], {x, 0, 1/2}, PlotStyle -> Thick,
ColorFunction -> Function[{x, y}, Hue[x]],
ColorFunctionScaling -> cf], {cf, {False, True}}]
When I evaluate it myself on Mathematica 7, both output plots look like the one on the left.
However, if I evaluate this, I get the plot on the right, as shown above:
Plot[Sin[4 Pi x], {x, 0, 1/2}, PlotStyle -> Thick,
ColorFunction -> Function[{x, y}, Hue[x]],
ColorFunctionScaling -> True]
Why might the example as given fail?
Alexey and Simon demonstrated that this is not the result of HoldAll, as I presumed before.
The existence of the example leads me to suspect it once worked, and the information that it works on version 8 tells me that the behavior has changed. What precisely has changed?

Your question is really interesting. The mentioned method of supplying option values to built-in functions is widely used in the Documentation. The fact that it fails only for ColorFunctionScaling looks like a bug. And information that in v.8 this problem does not exist confirms that this is a bug in v.7.
In any way consider the following:
In[1]:= SetAttributes[f, HoldAll]
f[__, OptionsPattern[ColorFunctionScaling -> False]] :=
OptionValue[ColorFunctionScaling]
Table[f[Sin[4 Pi x], {x, 0, 1/2},
ColorFunctionScaling -> cf], {cf, {False, True}}]
Out[3]= {False, True}
You can see that HoldAll attribute in really does not prevent substituting of cf.
In this way, it is really interesting what was the cause of described buggy behavior of Plot with Table in v.7?

The evaluation order seems slightly out. It works if you force cf to be substituted in before the Plot command is looked at. To do this we use the With[{x=x},...] construct:
Table[With[{cf = cf},
Plot[Sin[4 Pi x], {x, 0, 1/2}, PlotStyle -> Thick,
ColorFunction -> Function[{x, y}, Hue[x]],
ColorFunctionScaling -> cf]], {cf, {False, True}}]
It's strange that you don't need such a kludge in Mathematica version 8.
It's even stranger that the Mathematica 7 documentation has an example where the pre-evaluated graphics does not match what is produced by that version. (Nice find, btw)

This bug in fact is related to the HoldAll attribute, but I was fooled by this auto-load issue into thinking it was not. This can be seen by executing this:
Plot[Sin[x], {x, 0, Pi}];
Unprotect[Plot]
ClearAttributes[Plot, HoldAll]
Table[Plot[Sin[4 Pi x], {x, 0, 1/2}, PlotStyle -> Thick,
ColorFunction -> Function[{x, y}, Hue[x]],
ColorFunctionScaling -> cf], {cf, {False, True}}]
The first Plot is needed to activate the package load.
One can therefore get the correct behavior by wrapping ColorFunctionScaling -> ... in Evaluate:
Table[Plot[Sin[4 Pi x], {x, 0, 1/2}, PlotStyle -> Thick,
ColorFunction -> Function[{x, y}, Hue[x]],
Evaluate[ColorFunctionScaling -> cf]], {cf, {False, True}}]

Related

Two-dimensional error bars with ErrorPlotList in Mathematica?

I am brand new to Mathematica and am having trouble putting two-dimensional error bars on a graph. I have a table with the data format: (r, sr, x, sx, y, sy) where r, x, and y are means and sr, sx, and sy are the standard deviations. I want to plot the x versus y columns and did this successfully with ListPlot:
Show[
ListPlot[meanlist[[All, {3, 5}]]], Graphics[Circle[{0, 0}, 20]],
PlotRange -> All, AspectRatio -> 1,
AxesLabel -> {Style["y [mm]", Bold, Medium],
Style["z [mm]", Bold, Medium]},
AxesOrigin -> {0, 0}]
If really necessary, I could leave it at that. However, I also want to add the x and y error bars. I tried doing this using ErrorListPlot:
ErrorListPlot[{{meanlist[[All, {3, 5}]]},
ErrorBar[meanlist[[All, {4, 6}]]]},
PlotRange -> All, AspectRatio -> 1,
AxesLabel -> {Style["y [mm]", Bold, Medium],
Style["z [mm]", Bold, Medium]},
AxesOrigin -> {0, 0},
ErrorBarFunction -> Automatic]
What I get out is the following (I truncated the two lists after the first line because they are long):
ErrorListPlot[{{{{-5.34473, -9.16194}, {-7.87379, -6.57843},...,
ErrorBar[{{0.501015, 0.72511}, {0.48202, 0.703881},...,
AxesLabel -> {Style["y [mm]", Bold, Medium],
Style["z [mm]", Bold, Medium]},
AxesOrigin -> {0, 0},
ErrorBarFunction -> Automatic]
In other words, it spits out lists of properly paired coordinates and error amounts followed by all the parameters I set for the graph, but it does not actually create a plot. I have included Needs["ErrorBarPlots`"]; and I'm no sure what else could be wrong. Any ideas?
try this:
ErrorListPlot[
{#[[{3, 5}]], ErrorBar[#[[4]], #[[6]]] } & /# meanlist ]
Aside, The final result you saw is typical of mathematica when you supply a function with invalid arguments, it repeats back what you entered rather than reporting an error.

Plotlegend in Mathematica does not work for a table of functions

I am trying to plot a list of functions with a legend using PlotLegend in Mathematica v8. As a simple test illustrating what I'm trying to do.
<<PlotLegends`
test = Table[f[x], {f, {Sin, Cos, Tan, Log, Exp}}]
Plot[test, {x, 0, 1}, PlotRange -> Full, Axes -> {True, False},
PlotStyle -> Thick, AxesOrigin -> {0, 0},
PlotLegend -> {"Sin", "Cos", "Tan", "Log", "Exp"},
LegendPosition -> {0, -0.5}, LegendShadow -> None]
Gives as output
{Sin[x], Cos[x], Tan[x], Log[x], E^x}
However, if I explicitly put the table in the Plot command, I get the correct legend.
Plot[{Sin[x], Cos[x], Tan[x], Log[x], Exp[x]}, {x, 0, 1},
PlotRange -> Full, Axes -> {True, False}, PlotStyle -> Thick,
AxesOrigin -> {0, 0},
PlotLegend -> {"Sin", "Cos", "Tan", "Log", "Exp"},
LegendPosition -> {0, -0.5}, LegendShadow -> None]
For my actual application, I'm putting together a list of functions within a Do loop, so the latter Plot command is not ideal.
Any suggestions would be greatly appreciated.
Cheers,
Mike
Replace Plot[test, ...] with Plot[Evaluate#test, ...].
The problem is that Plot takes the first argument unevaluated and only evaluates it when calculating points. Therefore when it determines the labels, it only sees a single argument test, not a list, and therefore it only outputs one label. Evaluate#test tells Mathematica to evaluate test before passing it to Plot even though Plot is defined to take the argument unevaluated. This way, Plot sees the list you stored in test and knows to generate several labels.

histogram without vertical lines in Mathematica

I am trying to make an histogram without vertical lines. I'd like to have a plot which looks like a function. Like this:
The same question has been asked for R before ( histogram without vertical lines ) but I'm on Mathematica.
I have been looking into the ChartStyle options without success.
You could also use ListPlot with InterpolationOrder->0:
(* example data *)
data = RandomVariate[NormalDistribution[], 10^3];
hist = HistogramList[data, {.5}];
ListPlot[Transpose[{hist[[1]], ArrayPad[hist[[2]], {0, 1}, "Fixed"]}],
InterpolationOrder -> 0,
Joined -> True,
AxesOrigin -> {hist[[1, 1]], 0}]
There probably are ways to do this by fiddling with EdgeForm[] and FaceForm[] in Histogram, but I've found it simpler to roll one on my own, whenever I need it. Here's a very simple and quick example:
histPlot[data_, bins_, color_: Blue] := Module[{
countBorder =
Partition[Riffle[Riffle[#1, #1[[2 ;;]]], Riffle[#2, #2]], 2] & ##
HistogramList[data, bins, "PDF"]
},
ListLinePlot[countBorder, PlotStyle -> color]
]
Doing histPlot[RandomReal[NormalDistribution[],{1000}],{-3,3,0.1}] gives
You can then extend this to take any option instead of just "PDF", and for cases when you'd like to choose the bins automatically. I dislike automatic binning, because I like to control my bin widths and extents for predictability and easy comparison against other plots.
Here are two methods that work in version 7, using post-processing:
rdat = RandomReal[NormalDistribution[0, 1], 200];
MapAt[
{Blue,
Line[# /. {{Rectangle[{x_, y_}, {X_, Y_}]}} :> Sequence[{x, Y}, {X, Y}]] } &,
Histogram[rdat, PerformanceGoal -> "Speed"],
{1, 2, 2, 2}
]
Cases[
Histogram[rdat, PerformanceGoal -> "Speed"],
Rectangle[{x_, y_}, {X_, Y_}] :> {{x, Y}, {X, Y}},
\[Infinity]
];
Graphics[Line[Join ## %], AspectRatio -> 1/GoldenRatio, Axes -> True]

Histogram plots in LevelScheme

I've just started using LevelScheme, and have issues with getting the histogram to fit correctly within the figure. A minimal non-working example:
<<"LevelScheme`"
Figure[{FigurePanel[{{0, 1}, {0, 1}},
LabB -> textit["x"], BufferB -> 2.5,
LabL -> textit["p(x)"], BufferL -> 2.5,
FrameTicks -> {LinTicks[-4, 4], LinTicks[0, 1]},
PlotRange -> {{-3, 3}, {0, 0.5}}],
RawGraphics[
Histogram[RandomReal[NormalDistribution[], 1000], Automatic,
"ProbabilityDensity"]]},
Frame -> False, PlotRange -> {{-0.075, 1.1}, {-0.1, 1.03}}]
The output looks like this
when it should look like this
Basically, the Histogram graphics object doesn't obey the FigurePanel's PlotRange, but instead obeys the main Figure's PlotRange. This behaviour doesn't occur when the Histogram is replaced by a Plot or similar commands. So the following produces a clean plot
Figure[{FigurePanel[{{0, 1}, {0, 1}},
LabB -> textit["x"], BufferB -> 2.5,
LabL -> textit["p(x)"], BufferL -> 2.5,
FrameTicks -> {LinTicks[-4, 4], LinTicks[0, 1]},
PlotRange -> {{-3, 3}, {0, 0.5}}],
RawGraphics[Plot[1/Sqrt[2 Pi] Exp[-x^2/2], {x, -4, 4}]]},
Frame -> False, PlotRange -> {{-0.075, 1.1}, {-0.1, 1.03}}]
Has anyone else encountered this issue? Or, do you have suggestions for a fix?
EDIT
I thought I'd add some green to the question. I'm still interested in knowing how to overcome this hurdle.
Well, I recon you won't like this one too much but it is a workaround of sorts.
If I give PerformanceGoal -> "Speed" as a Histogram option (rather than PerformanceGoal -> "Quality") I disable interactive behaviour but, with a few minor tweaks, I get the following:
<< "LevelScheme`"
Figure[{FigurePanel[{{0, 1}, {0, 1}}, LabB -> textit["x"],
BufferB -> 2.5, LabL -> textit["p(x)"], BufferL -> 2.5,
FrameTicks -> {LinTicks[-4, 4], LinTicks[0, 1]},
PlotRange -> {{-3, 3}, {0, 0.55}}],
RawGraphics[
Histogram[RandomReal[NormalDistribution[], 1000], Automatic,
"ProbabilityDensity", PerformanceGoal -> "Speed"]]},
Frame -> False, PlotRange -> {{-0.075, 1.1}, {-0.15, 1.1}}]
As Simon mentioned in a comment, you can use LevelScheme's DataPlot to plot a histogram.
<< "LevelScheme`"
histData[x_] :=
Cases[x, RectangleBox[{bl_, _}, {br_, c_}] :> {{bl, br}, c},
Infinity];
hist = histData[
Histogram[RandomReal[NormalDistribution[], 1000], {-4, 4, 0.1},
"ProbabilityDensity"]];
bins = hist[[All, 1, 1]]; counts = hist[[All, 2]];
data = Table[{bins[[i]], counts[[i]]}, {i, 1, Length#counts}];
Figure[{FigurePanel[{{0, 1}, {0, 1}}, LabB -> textit["x"],
BufferB -> 2.5, LabL -> textit["p(x)"], BufferL -> 2.5,
FrameTicks -> {LinTicks[-4, 4], LinTicks[0, 1]},
PlotRange -> {{-3, 3}, {0, 0.5}}],
DataPlot[data,
DataLine -> {LineShape -> "Histogram", LineColor -> Darker#Blue},
DataSymbol -> {SymbolSize -> 0.00001}],
RawGraphics[
Plot[1/Sqrt[2 Pi] Exp[-x^2/2], {x, -4, 4},
PlotStyle -> {Red, Thick}]]
}, Frame -> False, PlotRange -> {{-0.075, 1.1}, {-0.1, 1.03}}]
However, I haven't managed to get filled histogram bars like that produced by Histogram or BarChart, if that was also what you had intended.
BTW, the function histData is similar to something I saw on a mathematica help forum long ago, and it went in my useful functions toolkit. I don't remember where I read that or when, to credit it. However, it is not all that of a magic function now to me, as it was back then.
I know what the problem is, but I don't have an immediate fix. The way LevelScheme works is that it transforms the Graphics objects so that they fit correctly. To do this, RawGraphics uses the legacy function TransformGraphics from LegacyPackages\Graphics\Graphics.m which is included in LegacyTransformGraphics.m in v. 3.51 of the LevelScheme packages. Looking at the FullForm of your Histogram, you can see that TransformGraphics knows nothing about dealing with the sort of objects produced. Mark Caprio is working on an update to LevelScheme over the next couple of months, so there may be a fix on the way. In the mean time, try using Rasterize before supply your histogram to RawGraphics, although it may not give you good results.
Edit:
Instead of using the legacy version of TransformGraphics, a more recent version might look like
TransformGraphics[
(g:(Graphics | Graphics3D))[prims__, opts:OptionsPattern[], transform_]:=
g[ GeometricTransformation[prims, transform], opts ]
Of course, the trick is now supplying a version of transform that GeometricTransformation can accept. Although, the legacy TransformGraphics, applies a function, its second argument, directly to the points found in g, so using the above code may work without any additional changes.
To try it, replace Needs["LevelScheme`LegacyTransformGraphics`"] with the above code in either LevelScheme.nb (and regenerate LevelScheme.m) or in LevelScheme.m directly. It may not work completely, as I don't see where the options are substituted, but it should be a start.

Getting coordinates of manually drawn points

I have a graph as a result of executing ListPlot[] function.
I can manually edit this graph by moving points to a different location
and also adding new points using the Drawing Tools.
How do I get the coordinates of new and changed points from the edited graphics?
I'm not sure if the following is anything like what you want,but nevertheless:
If I use ListPlot as follows:
lp1 = Labeled[
ListPlot[Diagonal#Table[{x, y}, {x, 0, 5}, {y, 5}],
PlotStyle -> {Directive[Red, PointSize[Large]]}], "lp1"];
By double clicking on one of the red points twice to get the selection to the level of the points, I can then move the individual points, e.g., to make the points lie on a curve (rather than a straight line). I now want to extract these points (and say use them in a new ListPlot) [see plots below]
If I click on the bracket of the plot graphic and use "Show Expression" (Command Shift E on a Mac), I can 'see' the coordinates of the modified points which may then be extracted. For example:
expr = Cell[
BoxData[GraphicsBox[{RGBColor[1, 0, 0], PointSize[Large],
PointBox[{{0., 1.}, {0.8254488458250212,
2.886651181634783}, {1.9301795383300084`,
3.925201233010209}, {3.046546974446661,
4.597525796319094}, {4., 5.}}]},
AspectRatio -> NCache[GoldenRatio^(-1), 0.6180339887498948],
Axes -> True, PlotRange -> Automatic,
PlotRangeClipping -> True]], "Input",
CellChangeTimes -> {{3.504427833788156*^9, 3.50442786823486*^9}}];
Modifying a very useful approach originally suggested by Yaroslav Bulatov, which may be found here
modpoints = Flatten[Cases[expr, PointBox[___], Infinity][[All, 1]], {{2, 1}}]
EDIT
As pointed out by belisarius, it is desirable to be able to extract 'manually' added points (which may be added to the generated plot using 'point' from the Drawing Tools palette). A better way of extracting (after 'Show Expression' ...) is probably the following:
modpoints = Cases[Cases[expr, PointBox[___],
Infinity], {_?NumericQ, _?NumericQ}, Infinity]
Of course, 'Show Expression' is not the only approach.
InputForm is another possibility. For example,
expr2 = InputForm[ListPlotGraphic]
modpoints = Cases[Cases[expr, Point[___],
Infinity], {_?NumericQ, _?NumericQ}, Infinity]
where "ListPlotGraphic" is the modified graphic (inserted by 'copy and paste'), will also work.
Example plots
Addendum
The above can be automated with a little notebook programming:
lp1 = Labeled[
ListPlot[Diagonal#Table[{x, y}, {x, 0, 5}, {y, 5}],
PlotStyle -> {Directive[Red, PointSize[Large]]}],
Button["Print points",
With[{nb = ButtonNotebook[]},
SelectionMove[nb, All, CellContents];
Print[Cases[NotebookRead[nb],
PointBox[{{_?NumericQ, _?NumericQ} ..}] |
PointBox[{_?NumericQ, _?NumericQ}], Infinity]]]]]
Running the above, moving the last two original (red) points and adding a couple of extra points in blue with the drawing tools then pressing the button yields
You can see that there is a single PointBox for the original data and a new PointBox for each of the added points. Of course, by modifying the above code, you can do more than simply print out the raw point coordinates.
This approach makes every data point a locator that can be moved. New locators can be added and old ones deleted as appropriate. The best fit and variance are updated after every change.
Here's some data of some exponential growth with some errors and a data point missing
data = Delete[Table[{t, (1 + RandomReal[{-.2, .2}])Exp[t]}, {t, 0, 2, .2}], 6];
A little formatting command:
nForm = NumberForm[#, {2, 2}, NumberPadding -> {"", "0"}] &;
Finally, here's the code to make the manipulable graphics. New locators/data points are added using Alt-Click (or Ctrl-Alt-Click on linux). If you click on the list of points on the left, then a new window is opened containing the points in input form.
Manipulate[
LocatorPane[Dynamic[pts, {None, Temporary, Automatic}],
nlm = Block[{a,b,t}, NonlinearModelFit[Sort[pts], a Exp[t] + b, {a, b}, t]];
Show[Plot[{Exp[t], nlm[t]}, {t, 0, 2},
PlotStyle -> {{Thick, LightGray}, Dotted}, PlotRangePadding -> Scaled[0.1]],
ListPlot[data, PlotStyle -> Blue], AxesLabel -> Block[{t,f}, {t, f[t]}]],
LocatorAutoCreate -> True, Appearance -> Style["\[CircleDot]", Red]],
{nlm, None}, {{pts, data}, None},
Dynamic[Pane[EventHandler[
nForm#Grid[Prepend[pts, {"x", "y"}], Dividers -> {False, 2 -> True}],
{"MouseClicked" :> (CreateDocument[{ExpressionCell[nlm["Data"], "Output"]},
WindowTitle -> "Data"])}], ImageSize -> {100, 250},
ImageSizeAction -> "Scrollable", Scrollbars -> {False, True}]],
Pane[Dynamic[nForm#Row#{nlm,Row[{"\tvariance = ",nlm["EstimatedVariance"]}]}]],
ControlPlacement -> {Left, Left, Left, Top}]
In the above I've used the locators to correct a couple of outliers and restored the missing data point.
The easy option is to use the "Get Coordinates" menu option. If you right click on the graphic, in the pop-up menu you'll see "Get Coordinates" which allows you to mouse-over a point and see that point's coordinates. Of course this isn't going to be accurate... but the way you're editing the graphic isn't very accurate either.
You could use the InputForm (or FullForm) function, but I am not sure how well this works...
In[1]:= a = ListPlot[{{1, 0}, {0, 1}, {1, 1}}];
a // InputForm
Out[2]//InputForm=
Graphics[{{{}, {Hue[0.67, 0.6, 0.6], Point[{{1., 0.}, {0., 1.}, {1., 1.}}]},
{}}}, {AspectRatio -> GoldenRatio^(-1), Axes -> True, AxesOrigin -> {0, 0},
PlotRange -> {{0., 1.}, {0., 1.}}, PlotRangeClipping -> True,
PlotRangePadding -> {Scaled[0.02], Scaled[0.02]}}]
You'll notice that there's a Point expression in there.
The third option would be to use Locator in some way I guess.

Resources